18

根据 3.6.0 文档:

CPython 实现细节:在 CPython 3.6 及更高版本中,单元格作为类命名空间中的条目__class__ 传递给元类。__classcell__如果存在,则必须将其传播到type.__new__ 调用才能正确初始化类。如果不这样做,将导致DeprecationWarningPython 3.6 中RuntimeWarning的 a 和未来的 a。

有人可以提供一个正确执行此操作的示例吗?

一个实际需要的例子?

4

1 回答 1

18

如果您使用依赖于类主体内__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是最终的补丁,来自Issue 23722

在向 Django 发出的拉取请求中可以看到一个正确执行此操作的示例,该请求使用它来修复 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__.

于 2016-12-27T14:31:17.023 回答