<p>问题是不应该用绑定方法替换<em>函数</em><code>add</code>。方法的工作方式是<code>function</code>对象有一个<code>__get__</code>方法,在实例方法的情况下,该方法返回一个绑定方法,供您在提供的参数上调用。也就是说</p>
<pre><code>class MyClass:
def add(self, x, y):
return x + y
def mul(self, x, y):
return x * y
o = MyClass()
</code></pre>
<p>像<code>o.add(3,5)</code>这样的调用等价于<code>type(o).__dict__['add'].__get__(o, type(o))(3,5)</code>。你知道吗</p>
<p>您的装饰器还应该简单地返回一个新函数,而不是一个<code>method</code>对象,并让它的<code>__get__</code>方法完成它的工作。你知道吗</p>
<p>你的新装饰师,有一些简化:</p>
<pre><code>def mydecorator(myobj):
@functools.wraps(myobj)
def decorated_method(*args, **kwargs):
print("I'm decorated!")
return myobj(*args, **kwargs)
# Decorating a function
if inspect.isfunction(myobj):
return decorated_method
# Decorating a class
if inspect.isclass(myobj):
if "add" in myobj.__dict__:
setattr(myobj, "add", mydecorator(obj))
# Or just setattr(myobj, "add", decorated_method),
# unless you think myobj.add might be a nested class
return myobj
# Anything else is type error.
raise TypeError("can decorate only classes and functions")
</code></pre>
<hr/>
<p>解决一些其他问题。。。你知道吗</p>
<blockquote>
<p>How does Python internally discriminate a normal method from a @classmethod or a @staticmethod?</p>
</blockquote>
<p><code>classmethod</code>和<code>staticmethod</code>对象返回的对象具有与常规<code>function</code>对象不同的<code>__get__</code>方法。你知道吗</p>
<blockquote>
<p>Where would I have found the documentation of all this?</p>
</blockquote>
<p><a href="https://docs.python.org/3.7/howto/descriptor.html" rel="nofollow noreferrer">Descriptor How-to Guide</a>是一个很好的起点。它描述了描述符协议,以及属性和方法如何使用它的示例。你知道吗</p>