查看Python 3.5中类型的文档super
,它指出super(…)
与super(__class__, «first argument to function»)
. 令我惊讶的是,我编写了一个返回的方法__class__
——它确实有效:
>>> class c:
... def meth(self): return __class__
...
>>> c().meth()
<class '__main__.c'>
显然,__class__
是一个由函数闭包分配的自由变量:
>>> c.meth.__code__.co_freevars
('__class__',)
>>> c.meth.__closure__
(<cell at 0x7f6346a91048: type object at 0x55823b17f3a8>,)
我想知道在什么情况下自由变量与闭包相关联。我知道,如果我在创建类的过程中将函数分配给变量,则不会发生。
>>> def meth2(self): return __class__
...
>>> meth2.__code__.co_freevars
()
即使我创建了一个新类并作为该创建的一部分为 分配了一些属性meth2
,meth2
也不会以某种方式神奇地获得一个被填充的自由变量。
这并不奇怪,因为其中一部分似乎取决于编译器在编译代码时的词法状态。
我想确认__class__
被视为自由变量的必要条件很简单:
- 代码块中的引用
__class__
;和 def
包含引用的__class__
词法在class
声明块中。
我还想了解正确填写该变量所需的条件是什么。似乎——至少从 Python 3.6 文档来看——以type.__new__(…)
某种方式涉及到类似的东西。我无法确定如何type
发挥作用,以及这一切如何与最终不调用type.__new__(…)
.
我特别困惑,因为当时我不认为命名空间的__setattr__
方法用于将包含方法的属性分配给方法函数(因为它存在于最终构造的类对象上)。我知道这个命名空间对象的存在是因为它要么是通过使用class
语句隐式构造的,要么是由元类的__prepare__
方法显式构造的——但据我所知,元类构造了在函数对象设置为__class__
之后填充的类对象类命名空间中的值。