<p>self什么都不做。<em>self</em>只是Python类定义中方法的第一个参数的常规名称。此参数将被传递给类的实例。你知道吗</p>
<p>本质上,要理解实际发生的事情,您必须理解Python描述符。最好的地方是官方的<a href="https://docs.python.org/3/reference/datamodel.html#implementing-descriptors" rel="nofollow noreferrer">docs</a>
简而言之,描述符对象是实现<code>__get__</code>、<code>__set__</code>或<code>__delete__</code>的对象。这些方法拦截对象属性访问、对象属性分配和对象属性删除。你知道吗</p>
<p>另外,请查看<a href="https://docs.python.org/3/howto/descriptor.html#descriptor-howto-guide" rel="nofollow noreferrer">HOWTO</a>,其中显示了Python如何实现<a href="https://docs.python.org/3/howto/descriptor.html#functions-and-methods" rel="nofollow noreferrer">functions and methods are simply descriptors</a>,并显示了一个Python实现示例(当然,在CPython中,这是用C实现的):</p>
<pre><code>class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
return types.MethodType(self, obj)
</code></pre>
<p>我们可以“欺骗”并创建我们自己的对象,只包装一个函数对象,然后看看这是否有效。你知道吗</p>
<pre><code>import types
class Function:
def __init__(self, func):
self._func = func
def __call__(self, *args, **kwargs):
return self._func(*args, **kwargs)
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c https://docs.python.org/3/howto/descriptor.html#functions-and-methods"
if obj is None:
return self
else:
return types.MethodType(self, obj)
class Foo:
def __init__(self):
self.foo = 42
bar = Function(lambda self:
self.foo ** 2
</code></pre>
<p>或者,在REPL中:</p>
<pre><code>>>> import types
>>>
>>> class Function:
... def __init__(self, func):
... self._func = func
... def __call__(self, *args, **kwargs):
... return self._func(*args, **kwargs)
... def __get__(self, obj, objtype=None):
... "Simulate func_descr_get() in Objects/funcobject.c https://docs.python.org/3/howto/descriptor.html#functions-and-methods"
... if obj is None:
... return self
... else:
... return types.MethodType(self, obj)
...
>>> class Foo:
... def __init__(self):
... self.foo = 42
... bar = Function(lambda self:
... self.foo ** 2
... )
...
>>> Foo().bar()
1764
</code></pre>
<p>这向您展示了“self”背后的魔力仅仅是函数对象<em>是描述符</em>,它们实现了一个<code>__get__</code>方法,如果在没有实例的情况下调用该方法,则返回函数本身,或者返回绑定第一个参数的方法对象。你知道吗</p>