Reputation: 31569
I'm trying to do a sort of type handling function registration, using this code:
types = {}
def type_handler(name):
def wrapper(f):
types[name] = f
return f
return wrapper
@type_handler('a')
def handle_a(a):
...
@type_handler('b'):
def handle_b(b):
...
def handle(x):
types[x.name](x)
This works fine, but now I want it to work inside a class.
I tried this:
class MyClass(object):
types = {}
def type_handler(name):
def wrapper(f):
types[name] = f ## global name 'types' is undefined
return f
return wrapper
@type_handler('a')
def handle_a(self, a):
...
@type_handler('b'):
def handle_b(self, b):
...
def handle(self, x):
self.types[x.name](self, x)
But it says global name 'types' is undefined
.
I tried changing it to
def type_handler(name):
def wrapper(f):
MyClass.types[name] = f ## global name 'MyClass' is undefined
return f
return wrapper
But now it says global name 'MyClass' is undefined
.
What can I do to make this work?
I know I can do something like:
def handle(self, x):
self.__getattribute__('handle_%s' % x.name)(self, x)
But I prefer function registration rather name based lookup.
Upvotes: 1
Views: 146
Reputation: 24788
I agree with Sven Marnach. You should use "less magic". However, here is a quick fix:
#decorator is declared outside of class and type dict is passed in as an argument
def type_handler(name, type_dict):
def wrapper(f):
type_dict[name] = f
return f
return wrapper
class MyClass(object):
types = {}
@type_handler('a', types)
def foo_a(self, a):
pass
@type_handler('b', types)
def foo_b(self, b):
pass
VERSION 2
This one uses a class as a decorator:
class TypeHandler(object):
def __init__(self, type_dict):
self.types = type_dict
def __call__(self, name):
def wrapper(f):
self.types[name] = f
return f
return wrapper
class MyClass(object):
types = {}
thandle = TypeHandler(types)
@thandle('a')
def foo_a(self, a):
pass
Upvotes: 3