查看the documentation of the ^{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__
的引用;及__class__
引用的def
在词汇上位于class
声明块中李>我想进一步了解正确填写该变量所需的条件。至少从Python3.6文档来看,似乎某种程度上涉及了type.__new__(…)
之类的内容。我还不能确定type
是如何起作用的,以及这一切是如何与最终不调用type.__new__(…)
的元类交互的
我特别困惑,因为当时我不认为名称空间的__setattr__
方法用于将包含该方法的属性分配给方法函数(因为它存在于最终构造的类对象上)。我知道这个名称空间对象之所以存在,是因为它要么是通过使用class
语句隐式构造的,要么是通过元类的__prepare__
方法显式构造的——但正如我所知,元类构造了填充__class__
的类对象在之后,函数对象被设置为类名称空间中的值
在the docs for Python’s data model、§ 3.3.3.6—“创建类对象”中,您将发现以下内容:
…重点是我的。这确认了发生
__class__
闭包的两个假定条件:方法def中的“__class__
”引用,它本身在class
语句中定义但是,在“创建类对象”中的下一篇文章接着说:
…重点是他们的。这意味着,如果您使用带有
__new__
方法的元类,以便指定创建此类的术语,例如:…最后的),则可能会在此处和此处之间调用其他一些祖传的“
super(…).__new__(…)
调用实际上是在调用type.__new__(…)
。在现实生活中,如果您的元类继承自其他元类(例如^{__new__(…)
”方法。实际上,在Meta.__new__(…)
方法内部,在方法入口点super(…).__new__(…)
调用和return
调用新类对象之间,您可以通过attributes['__classcell__']
检查或设置最终__class__
单元格变量的值至于这是否有用,我不知道。我已经在python编程十年了;我完全使用元类——比如,绝对一直使用元类(不管是好是坏);在此过程中,我从未做过以下任何事情:
__class__
属性李>__class__
单元格变量的任何内容;也不是__classcell__
名称空间条目弄乱了…很自然,你的编程经验将不同于我,谁知道你会做什么。上述战略中的任何一个都不是事实上的问题。但我对任由Python的类型系统和元编程工具随心所欲并不陌生,而且这些特殊的东西从来没有表现出特别有用,特别是当您在元类的一般上下文中工作时,以及它们所做的事情
我想我的意思是,tl;dr:你正处在了解元类的基础知识和它们能做什么的关键时刻——继续努力并进行实验,但一定要用深度和呼吸来研究这个主题。真的
†–在阅读此类代码示例时,您经常会发现我的代码片段称之为
attributes
字典,称之为namespace
或ns
或类似字典。都是一样的东西——…以及ABC、混音器、班级装饰器和
__init_subclass__(…)
以及滥用__mro_entries__(…)
谋取私利等等,无趣相关问题 更多 >
编程相关推荐