我想寫一個裝飾器,提供方法重載功能到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