Last active
August 31, 2016 07:02
-
-
Save L3viathan/6f2df79571d7788accd95cc646b379e1 to your computer and use it in GitHub Desktop.
Horrible abuse of Python's magic methods to make a more magic version of itemgetter/attrgetter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import operator as op | |
from functools import partial | |
class _getter(object): | |
def __init__(self, *, is_original=True): | |
self.is_original=is_original | |
self.__ops = [] | |
def __call__(self, something): | |
''' Maybe eventually extend to act like methodcaller, but problems exist''' | |
if self.is_original: | |
return _getter(is_original=False) | |
for function in self.__ops: | |
something = function(something) | |
return something | |
def __getattr__(self, attr): | |
'''getter.foo''' | |
if attr.startswith('__'): | |
return super().__getattr__(self, attr) | |
if self.is_original: | |
return _getter(is_original=False).__getattr__(attr) | |
self.__ops.append(op.attrgetter(attr)) | |
return self | |
def __getitem__(self, item): | |
'''getter[foo]''' | |
if self.is_original: | |
return _getter(is_original=False).__getitem__(item) | |
self.__ops.append(op.itemgetter(item)) | |
return self | |
def __matmul__(self, other): | |
'''Not actually matmul. getter@function. Applies function.''' | |
if self.is_original: | |
return _getter(is_original=False).__matmul__(other) | |
self.__ops.append(other) | |
return self | |
def __eq__(self, other): | |
'''map to boolean if evaluates to True''' | |
if self.is_original: | |
return _getter(is_original=False).__eq__(other) | |
self.__ops.append(partial(op.eq, other)) | |
return self | |
... | |
getter = _getter() | |
if __name__ == '__main__': | |
from random import randint | |
l = [(randint(0,20), randint(0,20)) for _ in range(10)] | |
print(l) # [(8, 0), (7, 8), (12, 8), (10, 13), (20, 18), (3, 20), (19, 7), (11, 18), (2, 16), (5, 0)] | |
print(sorted(l)) | |
# [(2, 16), (3, 20), (5, 0), (7, 8), (8, 0), (10, 13), (11, 18), (12, 8), (19, 7), (20, 18)] | |
print(sorted(l, key=getter[1])) | |
# [(8, 0), (5, 0), (19, 7), (7, 8), (12, 8), (10, 13), (2, 16), (20, 18), (11, 18), (3, 20)] | |
class Bar(): | |
def __init__(self): | |
self.n = (randint(1,20), randint(1, 20)) | |
@property | |
def foo(self): | |
return self.n | |
def __repr__(self): | |
return 'foo: ' + str(self.n) | |
L = [Bar() for _ in range(7)] | |
print(L) | |
# [foo: (10, 16), foo: (17, 1), foo: (17, 11), foo: (6, 14), foo: (18, 18), foo: (2, 13), foo: (13, 8)] | |
# sorted(L) # fails, unorderable types: Bar() < Bar() | |
print(sorted(L, key=getter.foo[1])) | |
# [foo: (17, 1), foo: (13, 8), foo: (17, 11), foo: (2, 13), foo: (6, 14), foo: (10, 16), foo: (18, 18)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So.... I took this a step further.
It's now in the
magic
module of toolib.