【发布时间】:2012-07-07 00:31:34
【问题描述】:
我正在尝试编写一个装饰器,为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 中的参考实现,或 pje 早期 PEP 和列表帖子所附的十几个其他参考实现?如果您尝试实际使用它,而不是尝试探索 Python,那么使用他的工作(至少其他一些人已经使用并测试过)可能比重复它更有意义。
-
@abarnert:我不知道这一点。感谢您的提醒。话虽如此,我真的只是想知道为什么我的实现没有按预期工作以及如何解决它。正如你所说,我是“探索 Python”。
-
首先,你知道@functools.wraps等吗?他们会让你的生活更轻松,但这对你没有帮助。无论如何,这里问题的第一部分是您的 default_function 被替换为类似函数的类,它不是方法(Overload.__call__ 需要一个自我,但那是 Overload 实例,而不是 MyClass)。但显然你不能只做 __call__(self, realself, *args, **kwargs) 并期望它起作用。我今晚没有时间详细介绍;希望其他人能在我回来之前提供帮助。