Last active
December 14, 2015 13:48
-
-
Save dplepage/5095902 to your computer and use it in GitHub Desktop.
Python metahack that allows you to use class-creation syntax to actually call arbitrary functions. This is useful for e.g. creating anonymous functions as arguments to other functions.
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
def ActuallyCalls(fn, namearg=None): | |
class __ActuallyCalls(object): | |
class __metaclass__(type): | |
def __new__(cls, name, supers, kwargs): | |
if name == '__ActuallyCalls': | |
return type.__new__(cls, name, supers, kwargs) | |
kwargs.pop('__module__', None) | |
if namearg: | |
kwargs[namearg] = name | |
return fn(**kwargs) | |
return __ActuallyCalls |
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
from actually import ActuallyCalls | |
def foo(a, b, fn=None): | |
if fn is None: | |
return a+b | |
return fn(a,b) | |
# Equivalent to x = foo(a=1, b=2) | |
class x(ActuallyCalls(foo)): | |
a = 1 | |
b = 2 | |
assert x == 3 | |
# Equivalent to defining the fn below, then y = foo(a=1, b=2, fn=fn) | |
class y(ActuallyCalls(foo)): | |
a = 1 | |
b = 2 | |
def fn(a, b): | |
return a*b*3 | |
assert y == 6 | |
# Nesting! z will equal 11. | |
class z(ActuallyCalls(foo)): | |
# a = 12 | |
class a(ActuallyCalls(foo)): | |
a = 5 | |
b = 7 | |
# b = 10 | |
class b(ActuallyCalls(foo)): | |
a = 'hello' | |
b = 'world' | |
def fn(a,b): | |
return len(a + b) | |
def fn(a,b): | |
return (a+b)/2 | |
assert z == 11 | |
# The namearg parameter allows you to pass in the name of the class as an arg. | |
def bar(name, x): | |
return "{} -> {}".format(name, x) | |
# Equivalent to tmp = bar(name='tmp', x=12) | |
class tmp(ActuallyCalls(bar, namearg='name')): | |
x = 12 | |
assert tmp == 'tmp -> 12' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment