self 什么都不做。 self 只是 Python 类定义中方法的第一个参数的常规名称。这个参数将被传递一个类的实例。
本质上,要了解实际发生的情况,您必须了解 Python 描述符。最好的地方是官方docs
简而言之,描述符对象是实现__get__、__set__ 或__delete__ 的对象。这些方法拦截对象属性访问obj.x、对象属性赋值obj.x = 42和对象属性删除del obj.x。
另外,查看HOWTO,他们在其中展示了 Python functions and methods are simply descriptors,并展示了 Python 实现示例(当然,在 CPython 中,这是在 C 中实现的):
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)
我们可以“作弊”并创建我们自己的对象,该对象仅包装一个函数对象,并看到这是有效的。
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
和或,在 REPL 中:
>>> 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
这向您展示了“self”背后的魔力仅仅是函数对象是描述符,它们实现了一个__get__ 方法,如果在没有实例的情况下调用该函数本身,或者返回一个绑定第一个参数的方法对象。