查看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__ 之后填充的类对象类命名空间中的值。