Skip to content

Instantly share code, notes, and snippets.

@dplepage
Last active December 14, 2015 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dplepage/5095902 to your computer and use it in GitHub Desktop.
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.
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
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