Provide __classcell__ example for Python 3.6 metaclass

强颜欢笑 提交于 2019-11-28 11:12:47

The warning is raised if you use the zero argument super super().__method__(args) that relies on __class__ being available or reference __class__ inside the class body.

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__.

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)

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.

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)

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!