我想写一个装饰器,提供方法重载功能到python,类似于PEP 3124中提到的。重载装饰器的方法
我写的装饰器对于普通函数非常适用,但是我无法让它在类中为方法工作。
这里是装饰:
class Overload(object):
def __init__(self, default):
self.default_function = default
self.type_map = {}
self.pos = None
def __call__(self, *args, **kwargs):
print self
try:
if self.pos is None:
pos = kwargs.get("pos", 0)
else:
pos = self.pos
print args, kwargs
return self.type_map[type(args[pos])](*args, **kwargs)
except KeyError:
return self.default_function(*args, **kwargs)
except IndexError:
return self.default_function(*args, **kwargs)
def overload(self, *d_type):
def wrapper(f):
for dt in d_type:
self.type_map[dt] = f
return self
return wrapper
当我试图实现它是这样的:
class MyClass(object):
def __init__(self):
self.some_instance_var = 1
@Overload
def print_first_item(self, x):
return x[0], self.some_instance_var
@print_first_item.overload(str)
def print_first_item(self, x):
return x.split()[0], self.some_instance_var
我得到一个TypeError
当我运行它:
>>> m = MyClass()
>>> m.print_first_item(1)
<__main__.Overload object at 0x2> (1,) {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "overload.py", line 17, in __call__
return self.default_function(*args, **kwargs)
TypeError: print_first_item() takes exactly 2 arguments (1 given)
>>>
我的问题是:如何访问MyClass
的实例(即self
)从装饰的方法?
有你看在PEAK.Rules参考实现,或任何十几连接到司法警察的其他参考实现较早的PEP和列表帖子?如果你试图真正使用它,而不是试图探索Python,那么使用他的作品(至少有其他人已经使用和测试过)比重复它更有意义。 – abarnert 2012-07-07 00:38:23
@abarnert:我没有意识到这一点。感谢您的高举。这就是说,我真的只是想知道为什么我的实现没有按预期工作,我怎么能解决它。我就像你说的“探索Python”一样。 – 2012-07-07 00:42:24
首先,你知道@ functools.wraps等吗?他们会让你的生活变得更轻松,但这不会帮助你。无论如何,这里问题的第一部分是,你的default_function被一个类似函数的类替换,它不是一个方法(Overload .__ call__需要一个self,但这是Overload实例,而不是MyClass)。但显然你不能只做__call __(自我,自己,* args,** kwargs),并期待这种工作。我今晚没有时间详谈了;希望别人能够在我回来之前提供帮助。 – abarnert 2012-07-07 01:00:49