提供Python 3.6元类的__classcell__示例
根据3.6.0文档:
CPython实现细节 :在CPython 3.6和更高版本中,
__class__
单元作为__classcell__
类名称空间中的条目传递到元类。如果存在,则必须将其传播到type.__new__
调用,以便正确初始化该类。如果不这样做,将导致DeprecationWarning
Python 3.6以及
RuntimeWarning
将来的版本。
有人可以提供正确执行此操作的示例吗?
一个实际需要它的例子?
-
如果您使用依赖于类体内的
__class__
可用或引用的super,则会发出警告__class__
。文字实质上是说,如果您定义自定义元类并在将其传递给之前篡改所获得的名称空间,则需要这样做
type.__new__
。你需要小心,始终确保你传递__classcell__
给type.__new__
你的metaclass.__new__
。也就是说,如果您创建了一个要传递的新名称空间,请始终检查是否
__classcell__
在创建的原始名称空间中定义了该名称空间并将其添加:class MyMeta(type): def __new__(cls, name, bases, namespace): my_fancy_new_namespace = {....} if '__classcell__' in namespace: my_fancy_new_namespace['__classcell__'] = namespace['__classcell__'] return super().__new__(cls, name, bases, my_fancy_new_namespace)
您在注释中链接的文件实际上是尝试发行的许多补丁程序中的第一个,
issue23722_classcell_reference_validation_v2.diff
也是发出此文件的最后一个补丁程序,发行于23722。正确执行此操作的示例可以在对Django发出的pull请求中看到,该请求使用此请求修复了Python
3.6中引入的问题:new_attrs = {'__module__': module} classcell = attrs.pop('__classcell__', None) if classcell is not None: new_attrs['__classcell__'] = classcell new_class = super_new(cls, name, bases, new_attrs)
在
__classcell__
传递之前被简单地添加到新的命名空间type.__new__
。