Auto-register class methods using decorator
If you need the classes name, use Matt's solution. However, if you're ok with just having the methods name -- or a reference to the method -- in the registry, this might be a simpler way of doing it:
class Registry:
r = {}
@classmethod
def register(cls, *args):
def decorator(fn):
cls.r[fn.__name__] = args
return fn
return decorator
class MyClass(object):
@Registry.register("prop1","prop2")
def my_method( arg1,arg2 ):
pass
@Registry.register("prop3","prop4")
def my_other_method( arg1,arg2 ):
pass
print Registry.r
{'my_other_method': ('prop3', 'prop4'), 'my_method': ('prop1', 'prop2')}
Not with just a decorator, no. But a metaclass can automatically work with a class after its been created. If your register
decorator just makes notes about what the metaclass should do, you can do the following:
registry = {}
class RegisteringType(type):
def __init__(cls, name, bases, attrs):
for key, val in attrs.iteritems():
properties = getattr(val, 'register', None)
if properties is not None:
registry['%s.%s' % (name, key)] = properties
def register(*args):
def decorator(f):
f.register = tuple(args)
return f
return decorator
class MyClass(object):
__metaclass__ = RegisteringType
@register('prop1','prop2')
def my_method( arg1,arg2 ):
pass
@register('prop3','prop4')
def my_other_method( arg1,arg2 ):
pass
print registry
printing
{'MyClass.my_other_method': ('prop3', 'prop4'), 'MyClass.my_method': ('prop1', 'prop2')}
Here's a little love for class decorators. I think the syntax is slightly simpler than that required for metaclasses.
def class_register(cls):
cls._propdict = {}
for methodname in dir(cls):
method = getattr(cls, methodname)
if hasattr(method, '_prop'):
cls._propdict.update(
{cls.__name__ + '.' + methodname: method._prop})
return cls
def register(*args):
def wrapper(func):
func._prop = args
return func
return wrapper
@class_register
class MyClass(object):
@register('prop1', 'prop2')
def my_method(self, arg1, arg2):
pass
@register('prop3', 'prop4')
def my_other_method(self, arg1, arg2):
pass
myclass = MyClass()
print(myclass._propdict)
# {'MyClass.my_other_method': ('prop3', 'prop4'), 'MyClass.my_method': ('prop1', 'prop2')}