<p>如果装饰方法已经过验证,那么只调用它怎么样?如果愿意,可以传递<code>validate</code>方法的返回值:</p>
<pre><code>class BaseClass(object):
def getvalue(self):
return True
def validate(input_function):
def wrapper(self, *args, **kwargs):
self.validated = self.getvalue()
if not self.validated:
print "Not validated."
return
input_function(self, validated=self.validated, *args, **kwargs)
return wrapper
validate = staticmethod(validate)
class ExtendedClass1(BaseClass):
@BaseClass.validate
def do_some_work(self, validated=None):
print "Things are validated if the method got this far.", validated
class ExtendedClass2(BaseClass):
@BaseClass.validate
def do_some_work(self, validated=None):
print "Things are validated if the method got this far.", validated
class ExtendedClass3(BaseClass):
def do_some_work(self):
print "This one doesn't require validation."
work1 = ExtendedClass1()
work1.do_some_work()
work2 = ExtendedClass2()
work2.do_some_work()
work3 = ExtendedClass3()
work3.do_some_work()
</code></pre>
<p>这里的关键是将<code>self</code>添加到<code>wrapper</code>函数中。所发生的情况是,修饰函数没有绑定到实例(并成为方法),而是由修饰器返回的函数(在上面的示例中是<code>wrapper</code>)绑定到实例。因此,此函数将在调用时获得传入的<code>self</code>(实例)参数!重要的是要记住,<code>@decorator</code>所做的只是调用<code>decorator</code>传入您正在装饰的函数,然后用装饰器返回的内容替换您正在装饰的函数。在您的示例中,这是<code>wrapper</code>,对于类来说,这与装饰之前的原始函数没有区别。你知道吗</p>
<p>在上面的例子中,我显式地声明了<code>self</code>。如果我们没有,我们也可以从<code>args</code>中得到它:</p>
<pre><code>def validate(input_function):
def wrapper(*args, **kwargs):
print "args[0] is now the instance (conventionally called 'self')", args[0]
self = args[0]
self.validated = self.getvalue()
if not self.validated:
print "Not validated."
return
input_function(validated=self.validated, *args, **kwargs)
</code></pre>
<p>还要注意,我们将一个额外的关键字参数传递给包装的方法,名为<code>validated</code>。这是完全可选的,您可以从示例中删除<code>validated=self.validated</code>和<code>validated=None</code>部分。你知道吗</p>