Reputation: 403
Say, I have a general function f(input, kind)
and a long list of kind
. I would like to create functions f_kind(input)
for each kind
in the list. Instead of doing it manually by f_kind1 = partial(f, kind=kind1)
, is it possible to create them more dynamically via a loop over the list (something similar to setattr(class_name, method_name, method)
inside a class)?
Upvotes: 0
Views: 50
Reputation: 123463
Your question reminded by of an article I read long ago by Guido van Rossum about implementing multimethods in Python — because at it's core, that's what you're doing.
It would need to be adapted to work on a class, but I think it might be a better approach than using setattr()
to achieve your goal.
mm.py:
''' MultiMethod module. '''
_registry = {}
class MultiMethod(object):
def __init__(self, name):
self.name = name
self.typemap = {}
def __call__(self, *args):
types = tuple(arg.__class__ for arg in args)
function = self.typemap.get(types)
if function is None:
raise TypeError("no match")
return function(*args)
def register(self, types, function):
if types in self.typemap:
raise TypeError("duplicate registration")
print('registering: {!r} for args: {}'.format(function.__name__, types))
self.typemap[types] = function
def multimethod(*types):
def register(function):
name = function.__name__
mm = _registry.get(name)
if mm is None:
mm = _registry[name] = MultiMethod(name)
mm.register(types, function)
return mm
return register
Sample usage.
mm_test.py:
from mm import multimethod
@multimethod(int)
def f(input):
print('f_{}({!r}) called'.format(type(input).__name__, input))
@multimethod(str)
def f(input):
print('f_{}({!r}) called'.format(type(input).__name__, input))
f('answer')
f(42)
@multimethod(float)
def f(input):
print('f_{}({!r}) called'.format(type(input).__name__, input))
f(3.141529)
Output:
registering: 'f' for args: (<class 'int'>,)
registering: 'f' for args: (<class 'str'>,)
f_str('answer') called
f_int(42) called
registering: 'f' for args: (<class 'float'>,)
f_float(3.141529) called
Upvotes: 1