Created
September 20, 2012 12:48
-
-
Save simon-engledew/3755683 to your computer and use it in GitHub Desktop.
Python ForEach Naughtiness
This file contains hidden or 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 __builtin__ | |
import operator | |
def merge(a, b): | |
a = a.copy() | |
a.update(b) | |
return a | |
class curry(object): | |
def __init__(self, fn, *args, **kwargs): | |
self.fn = fn | |
self.args = args | |
self.kwargs = kwargs.copy() | |
def __call__(self, *args, **kwargs): | |
return self.fn(*(self.args + args), **merge(self.kwargs, kwargs)) | |
def die(message, cls=Exception): | |
""" | |
Raise an exception, allows you to use logical shortcut operators to test for object existence succinctly. | |
User.by_name('username') or die('Failed to find user') | |
""" | |
raise cls(message) | |
def unguido(self, key): | |
""" | |
Attempt to find methods which should really exist on the object instance. | |
""" | |
return curry((getattr(__builtin__, key, None) if hasattr(__builtin__, key) else getattr(operator, key, None)) or die(key, KeyError), self) | |
class mapper(object): | |
def __init__(self, iterator, key): | |
self.iterator = iterator | |
self.key = key | |
self.fn = lambda o: getattr(o, key) | |
def __getattribute__(self, key): | |
if key in ('iterator', 'fn', 'key'): return object.__getattribute__(self, key) | |
return mapper(self, key) | |
def __call__(self, *args, **kwargs): | |
self.fn = lambda o: (getattr(o, self.key, None) or unguido(o, self.key))(*args, **kwargs) | |
return self | |
def __iter__(self): | |
for value in self.iterator: | |
yield self.fn(value) | |
class foreach(object): | |
""" | |
Creates an output iterator which will apply any functions called on it to every element | |
in the input iterator. A kind of chainable version of filter(). | |
E.g: | |
foreach([1, 2, 3]).__add__(2).__str__().replace('3', 'a').upper() | |
is equivalent to: | |
(str(o + 2).replace('3', 'a').upper() for o in iterator) | |
Obviously this will probably perform poorly and is not 'Pythonic'. | |
""" | |
def __init__(self, iterator): | |
self.iterator = iterator | |
def __getattribute__(self, key): | |
if key in ('iterator',): return object.__getattribute__(self, key) | |
return mapper(self.iterator, key) | |
def __iter__(self): | |
for value in self.iterator: | |
yield value | |
if __name__ == '__main__': | |
print list(foreach([1, 2, 3]).add(2).str().replace('3', 'a').upper()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment