为 Python 3.6 元类提供 __classcell__ 示例
Provide __classcell__ example for Python 3.6 metaclass
根据 3.6.0 文档:
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.
有人可以提供正确执行此操作的示例吗?
一个实际需要的例子?
如果您使用依赖 __class__
可用的 super 或在 class 正文中引用 __class__
,则会引发警告。
文本实质上说的是,如果您定义自定义元 class 并在将其传递到 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
is the final patch that made it in, from Issue 23722。
可以在 pull request made to 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__
之前只是添加到新的命名空间。
根据 3.6.0 文档:
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 thetype.__new__
call in order for the class to be initialized correctly. Failing to do so will result in aDeprecationWarning
in Python 3.6, and aRuntimeWarning
in the future.
有人可以提供正确执行此操作的示例吗?
一个实际需要的例子?
如果您使用依赖 __class__
可用的 super 或在 class 正文中引用 __class__
,则会引发警告。
文本实质上说的是,如果您定义自定义元 class 并在将其传递到 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
is the final patch that made it in, from Issue 23722。
可以在 pull request made to 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__
之前只是添加到新的命名空间。