Using 2.4 decorators with 2.2 and 2.3
在我昨天有关泛型函数的那篇Blog里,我说过你可以像在Python2.4中那样在Python2.2与2.3中使用PyProtocols的新decorators。
可我忽略了一点,就是这只对于PyProtocols的“魔力(magic)” decorators才好使,因为这个decorators是专门为该用途设计的。所以我听到了一些人的议论,他们试图在2.2和2.3中使用其他decorators,那当然不会行得通了。因此在这里我会列举一些小技巧,如果你想在Python2.2或2..3中使用decorator语法。
l 使用PyProtocols的CVS版本中的dispatch.as(),即:
class Foo(object):
[dispatch.as(classmethod)]
def something(cls, etc):
""" This will be a classmethod”””
你可以将多种decorators传递给dispatch.as(),它们将与2.4decorators中执行的顺序相同(如,最右优先<rightmost-first>)。
l 或者,你可以使用protocols.advice.add_assignment_advisor()来实现你自己的“魔力”decorators。尽管名字长得吓人,但你需要掌握的仅仅是如何编一个简单的回调(callback),这和一个标准2.4 decorator是一样的。下面是dispatch.as()的源码,给出了一个简单的回调实现:
""" Use Python 2.4 decorators w/Python 2.2+ """
if len(decorators) > 1 :
decorators = list(decorators)
decorators.reverse()
def callback(frame,name,value,old_locals):
for d in decorators:
value = d(value)
return value
return add_assignment_advisor(callback)
本质上说,你只是创建了一个实现了decorator功能的回调函数。对于简单decorators,你只需要回调中的value参数,即一个被装饰(being decorated)对象。更加复杂的decorators使用old_locals参数来访问先前定义的指定对象。但要注意,你的回调应总是使用已有框架和(或)old_locals,而不是试图直接使用sys._getframe()。这是因为实际调用回调的框架会发生变化,其取决于是否是使用2.4 '@'语法。
不管用哪种语法,当你获得了一个包含该泛型函数定义的框架引用时,add_assignment_advisor()便借此掩盖了这种差别。
最后要重点注意,这些“魔力”decorators使用了一些偷偷摸摸的手段:他们滥用sys.settrace()调试器钩子来跟踪发没发生赋值。虽然Guido对此十分怀疑,但钩子现有的泛函性在2.2,2.3或2.4中将不会改变,因此不要过于担心这一点。这的确是获得“早期访问”decorators的一个小秘诀,而且2.4的生命周期将长的足以让我们将代码转变到2.4语法上面。在Python2.5或2.6中的某个地方,add_assignment_advisor()可以放弃魔力部分而仅对使用它的decorators实现一个向后兼容的wrapper。
哦对了,还有件事…你没必要为使用add_assignment_advisor()而安装PyProtocols,因为它不依赖PyProtocols中的任何东西。你只需拖过来一个函数并将它拷到你自己的project中。
(原文链接网址:http://dirtsimple.org/2004/11/using-24-decorators-with-22-and-23.html)