是否可以使用类型正确复制 class

Is it possible to properly copy a class using type

根据this answer,一个class对象cls可以用

复制
cls_copy = type('cls_copy', cls.__bases__, dict(cls.__dict__))

这适用于大多数正常情况。当 cls 的元 class 不是 type 时,它 not 起作用。我最初天真的修复是做

cls_copy = type(cls)('cls_copy', cls.__bases__, dict(cls.__dict__))

然而,这根本没有意义。没有办法知道 metaclass 做了什么,正如 对相关问题指出的那样,它如何转换输入字典,它需要什么额外的关键字,等等。

type 的最初用途几乎已经足够好了,但有几个小例外:

  1. 由 metaclasses 创建的 __dict__ 最终不会调用 type.__new__ 的类型可能与通常的代理对象不同。
  2. 类 扩展副本将不会有正确的元数据class,这可能会导致意外行为。
  3. 原始元 class 中定义的任何属性或其他数据描述符将不再适用于 class 对象。

我愿意忽略第 1 项。如果我找到其他项目的可行解决方案,我愿意将其记录在案。如果可以更改副本的 metaclass,则可以解决项目 #2 和 #3。我试过(再一次,天真地)

cls_copy = type('cls_copy', cls.__bases__, dict(cls.__dict__),
                metaclass=type(cls))

正如预期的那样,这刚刚引发了 TypeError

TypeError: __init_subclass__() takes no keyword arguments

根据 docs:

这是有道理的

Like its identity, an object’s type is also unchangeable. 1

但是,footnote 指出

It is possible in some cases to change an object’s type, under certain controlled conditions. It generally isn’t a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly.

在什么条件下可以更改对象的类型,特别是 class 的类型?这是其中一种情况吗?如果是,情况如何?

备注

我知道 copy.deepcopy 和继承在这里是可行的选择。出于这个问题的目的,我希望忽略这些替代方案并坚持使用 type 相关技术。

您可以使用 type.__new__(type(cls), cls.__name__, cls.__bases__, dict(cls.__dict__))。这使用正常的 type 创建过程,但创建 type(cls) 的实例而不是 type.

至于__metaclass__的问题,我想是因为__metaclass__通常是叫什么的,所以type不能用