回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<h2>(我需要一位python3内部专家)</h2>
<p>我有一个<strong>类修饰符</strong>,它修改一些函数,但不修改其他函数。
简化示例:</p>
<pre><code>import functools
import inspect
import types
def mydecorator(myobj):
@functools.wraps(myobj)
def decorated_method(*args, **kwargs):
print("I'm decorated!")
return myobj(*args, **kwargs)
if inspect.isclass(myobj): # act as class decorator
for name, obj in myobj.__dict__.items():
if name == "add":
setattr(myobj, name, types.MethodType(mydecorator(obj), myobj))
return myobj # return decorated class
elif inspect.isfunction(myobj): # act as function decorator
return decorated_method
else:
assert False, "can decorate only classes and functions"
</code></pre>
<p>因此,这将修改任何<code>add</code>方法,以便在运行之前打印“我被装饰了”。你知道吗</p>
<p>我们将它应用于这个类:</p>
<pre><code>class MyClass:
def add(self, x, y): return x + y
def mul(self, x, y): return x * y
</code></pre>
<p>它工作正常。是的</p>
<pre><code>#--- try out undecorated MyClass:
print("MyClass.add:", MyClass.add, "MyClass.mul:", MyClass.mul)
print("3+4 =", MyClass().add(3, 4), "3*4 =", MyClass().mul(3, 4), )
#--- decorate MyClass:
print("MyClass = mydecorator(MyClass)")
MyClass = mydecorator(MyClass)
#--- try out decorated MyClass in the same manner:
print("MyClass.add:", MyClass.add, "MyClass.mul:", MyClass.mul)
print("3+4 =", MyClass().add(3, 4), "3*4 =", MyClass().mul(3, 4), )
</code></pre>
<p>并获取此输出(来自Linux上的cpython3.6.7)</p>
<pre><code>MyClass.add: <function MyClass.add at 0x7faededda0d0> MyClass.mul: <function MyClass.mul at 0x7faededda158>
3+4 = 7 3*4 = 12
MyClass = mydecorator(MyClass)
MyClass.add: <bound method MyClass.add of <class '__main__.MyClass'>> MyClass.mul: <function MyClass.mul at 0x7faededda158>
I'm decorated!
3+4 = 7 3*4 = 12
</code></pre>
<p>所以<code>mul</code>仍然是一个普通函数,而修饰的<code>add</code>变成了一个绑定方法。装饰工作正常。你知道吗</p>
<p>但是当我现在更改方法,使得<code>add</code>调用<code>mul</code>(忽略这个事实,这没有多大意义)如下:</p>
<pre><code>class MyClass:
def add(self, x, y): z = self.mul(x, y); return x + y
def mul(self, x, y): return x * y
</code></pre>
<p>输出变成:</p>
<pre><code>MyClass.add: <function MyClass.add at 0x7fbc760870d0> MyClass.mul: <function MyClass.mul at 0x7fbc76087158>
3+4 = 7 3*4 = 12
MyClass = mydecorator(MyClass)
MyClass.add: <bound method MyClass.add of <class '__main__.MyClass'>> MyClass.mul: <function MyClass.mul at 0x7fbc76087158>
I'm decorated!
Traceback (most recent call last):
File "tryout.py", line 34, in <module>
print("3+4 =", MyClass().add(3, 4), "3*4 =", MyClass().mul(3, 4), )
File "tryout.py", line 16, in decorated_method
return myobj(*args, **kwargs)
File "tryout.py", line 7, in add
def add(self, x, y): z = self.mul(x, y); return x + y # round 2
TypeError: mul() missing 1 required positional argument: 'y'
</code></pre>
<p>结果是<code>mul</code>(尽管和以前一样!)现在被调用,好像它是一个<code>@staticmethod</code>:<code>self</code>没有被传递。你知道吗</p>
<p>我有很多问题:</p>
<ol>
<li>这种惊人的效果从何而来?你知道吗</li>
<li><code>add</code>绑定到哪个对象?你知道吗</li>
<li>Python如何在内部区分普通方法与<code>@classmethod</code>或<code>@staticmethod</code>?你知道吗</li>
<li><code>types.MethodType</code>真正的意思是什么?你知道吗</li>
<li>我应该在它的位置写些什么来分别获得普通方法、类方法或静态方法?你知道吗</li>
<li>我在哪能找到这些文件?你知道吗</li>
<li>以下哪些答案与Python属性有关,而不是与CPython实现细节有关?你知道吗</li>
</ol>