提供Python 3.6元类的__classcell__示例

发布于 2021-01-29 18:20:24

根据3.6.0文档:

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

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

一个实际需要它的例子?

关注者
0
被浏览
51
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    如果您使用依赖于类体内的__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__



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看