<p>decorator所做的只是返回一个新函数。这:</p>
<pre><code>@deco
def foo():
# blah
</code></pre>
<p>与此相同:</p>
<pre><code>def foo():
# blah
foo = deco(foo)
</code></pre>
<p>你可以随时做同样的事情,不需要<code>@</code>语法,只要用你喜欢的东西替换函数。所以在<code>__init__</code>或者其他地方,您可以循环遍历所有方法,对于每个方法,用<code>smilewarmly(meth)</code>替换它。</p>
<p>但是,与其在<code>__init__</code>中执行,不如在创建类时执行。您可以使用一个元类,或者更简单地使用一个类装饰器:</p>
<pre><code>def smileDeco(func):
def wrapped(*args, **kw):
print ":-)"
func(*args, **kw)
return classmethod(wrapped)
def makeSmiley(cls):
for attr, val in cls.__dict__.iteritems():
if callable(val) and not attr.startswith("__"):
setattr(cls, attr, smileDeco(val))
return cls
@makeSmiley
class Foo(object):
def sayStuff(self):
print "Blah blah"
>>> Foo().sayStuff()
:-)
Blah blah
</code></pre>
<p>在本例中,我将classmethod装饰放在我的<code>smileDeco</code>装饰器中。你也可以把它放在<code>makeSmiley</code>中,这样<code>makeSmiley</code>返回<code>smileDeco(classmethod(val))</code>。(你想用哪种方法来实现它取决于smile decorator与classmethods的关系有多紧密)这意味着你不必在类中使用<code>@classmethod</code>。</p>
<p>当然,在<code>makeSmiley</code>的循环中,您可以包括您想要决定(例如,基于方法名)是否用微笑行为包装它的任何逻辑。</p>
<p>请注意,如果您真的想在类中手动使用<code>@classmethod</code>,那么就必须更加小心,因为通过类<code>__dict__</code>访问的类方法是不可调用的。因此,您必须特别检查对象是否是classmethod对象,而不是仅仅检查它是否可调用。</p>