根据3.6.0文档:
CPython实现细节:在CPython 3.6及更高版本中,
__class__
单元格以__classcell__
条目的形式传递到元类中。如果存在,则必须将其传播到type.__new__
调用中,以便正确初始化类。如果未能这样做,将在Python 3.6中产生一个DeprecationWarning
,并在未来产生一个RuntimeWarning
。
有人能提供一个正确的示例吗?
需要实际使用它的示例?
根据3.6.0文档:
CPython实现细节:在CPython 3.6及更高版本中,
__class__
单元格以__classcell__
条目的形式传递到元类中。如果存在,则必须将其传播到type.__new__
调用中,以便正确初始化类。如果未能这样做,将在Python 3.6中产生一个DeprecationWarning
,并在未来产生一个RuntimeWarning
。
有人能提供一个正确的示例吗?
需要实际使用它的示例?
如果你使用依赖于__class__
可用性或在类体内引用__class__
的super,就会发出警告。
文本基本上是说,如果你定义了一个自定义元类并且篡改了在传递给type.__new__
之前获得的命名空间,那么就需要这样做。你需要小心,并始终确保在metaclass.__new__
中将__classcell__
传递给type.__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__
。
super()
形式,就会创建它。这很可能是因为在元类方法本身内部调用任何使用super()
的classmethod以前是不可能的。更有可能的是,Python 3.6中的新__init_subclass__
机制需要它。 - jsbueno__init_subclass__
。如果你使用 type
就没问题了。 - Dimitris Fasarakis Hilliard