<p><a href="https://stackoverflow.com/a/27455032/908494">My other answer</a>解释了为什么现有代码不能工作,以及如何修复它(尽管我不确定它是如何解释的)。在</p>
<p>但是通常还有一种更简单的方法来完成您要做的事情:您可以对类进行monkeypatch,而不是包装它。当然,这意味着您必须使用<a href="https://docs.python.org/2/reference/datamodel.html#object.__getattribute__" rel="nofollow noreferrer">^{<cd1>}</a>而不是<a href="https://docs.python.org/2/reference/datamodel.html#object.__getattr__" rel="nofollow noreferrer">^{<cd2>}</a>,并附带所有有关意外递归调用自己的常见警告:*</p>
<pre><code>def Decor(cls):
old_getattribute = getattr(cls, '__getattribute__')
def new_getattribute(self, name):
print "attribute name of instance of class {} = {}".format(cls.__name__, name)
return old_getattribute(self, name)
cls.__getattribute__ = new_getattribute
return cls
</code></pre>
<p>这可能会打印出比您想要的更多的<em>例如,在<code>f = Foo(10)</code>期间,它将显示正在查找的<code>__class__</code>属性(<a href="https://docs.python.org/2/reference/datamodel.html#new-style-special-lookup" rel="nofollow noreferrer">but not ^{<cd5>}</a>)。当然,你可以过滤掉任何你不想记录的名字。在</p>
<p>这也有一些包装和委托没有的限制。它不能在旧样式的类上工作;你不能用它来动态包装内置或C扩展类;等等。另一方面,它确实意味着<code>Foo</code>有自己的名称,docstring等,而不是<code>Decor</code>,而不是{<cd7>},而不是{<cd7>}-样式。在</p>
<hr/>
<p><sub>*请注意,文档中说您应该始终调用基类版本来访问<code>__getattribute__</code>中的属性,但是在这种情况下,您希望调用{<cd10>}的原始版本,如果{<cd10>}没有定义基类版本,那么它当然是基类版本。</sub></p>