提供Python 3.6元类的__classcell__示例 [英] Provide __classcell__ example for Python 3.6 metaclass

查看:115
本文介绍了提供Python 3.6元类的__classcell__示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据3.6.0文档:

CPython实现细节:在CPython 3.6和更高版本中,__class__ 单元格作为类中的__classcell__条目传递给元类 命名空间.如果存在,则必须传播到type.__new__ 调用以便正确初始化该类.做不到 因此将在Python 3.6中生成DeprecationWarning,并且 RuntimeWarning将来.

CPython implementation detail: In CPython 3.6 and later, the __class__ cell is passed to the metaclass as a __classcell__ entry in the class namespace. If present, this must be propagated up to the type.__new__ call in order for the class to be initialized correctly. Failing to do so will result in a DeprecationWarning in Python 3.6, and a RuntimeWarning in the future.

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

Can someone provide an example of doing this correctly?

实际需要它的例子吗?

推荐答案

如果您使用依赖于类内部的__class__可用或引用__class__的super,则会发出警告.

The warning is raised if you use super that relies on __class__ being available or reference __class__ inside the class body.

从本质上讲,这是需要的,如果您定义一个自定义的元类并篡改所获得的名称空间,然后再将其传递给type.__new__.您需要小心,并始终确保在metaclass.__new__中将__classcell__传递给type.__new__.

What the text essentially says is that, this is needed if you define a custom meta-class and tamper with the namespace you get before passing it up to type.__new__. You'll need to be careful and always make sure you pass __classcell__ to type.__new__ in your metaclass.__new__.

也就是说,如果您创建了一个要传递的新名称空间,请始终检查是否在创建的原始名称空间中定义了__classcell__并将其添加:

That is, if you create a new fancy namespace to pass up, always check if __classcell__ is defined in the original namespace created and add it:

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 .

The file you linked in the comment is actually the first of many attempted patches, issue23722_classcell_reference_validation_v2.diff is the final patch that made it in, from Issue 23722.

可以在对Django进行的拉取请求中看到正确执行此操作的示例使用它来解决Python 3.6中引入的问题:

An example of doing this correctly can be seen in a pull request made to Django that uses this to fix an issue that was introduced in 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__.

The __classcell__ is simply added to the new namespace before being passed to type.__new__.

这篇关于提供Python 3.6元类的__classcell__示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆