是否可以使用type正确复制类 [英] Is it possible to properly copy a class using type
问题描述
根据此答案,可以使用以下方法复制类对象cls
According to this answer, a class object cls
can be replicated with
cls_copy = type('cls_copy', cls.__bases__, dict(cls.__dict__))
这在大多数正常情况下都非常有效.当cls
的元类不是type
时,不起作用.我最初的天真解决方法是
This works perfectly for most normal cases. It does not work when the metaclass of cls
is not type
. My initial naive fix was to do
cls_copy = type(cls)('cls_copy', cls.__bases__, dict(cls.__dict__))
但是,这根本没有意义.没有办法知道元类的作用,因为有关相关问题的答案指出,它如何转换输入词典,它还需要哪些其他关键字,等等.
However, this is simply pointless. There is no way to know what a metaclass does, as this answer to a related question points out, how it transforms the input dictionary, what additional keywords it requires, etc.
type
的原始用法几乎可以满足要求,但有一些次要的例外情况:
The original use of type
is almost good enough with a couple of minor exceptions:
- 由未最终调用
type.__new__
的元类创建的__dict__
的类型可能与通常的代理对象不同. - 扩展副本的类将没有正确的元类,这可能会导致意外行为.
- 在原始元类中定义的任何属性或其他数据描述符将不再在类对象上可用.
- The
__dict__
created by metaclasses that do not end up callingtype.__new__
may be of a different type than the usual proxy object. - Classes extending the copy will not have the correct metaclass, which may cause unexpected behavior.
- Any properties or other data descriptors defined in the original metaclass will no longer be available on the class object.
我愿意忽略项目#1.如果我想为其他项目找到可行的解决方案,那是我愿意记录下来的一个极端案例.如果可以更改副本的元类,则可以解决项目#2和#3.我尝试过(再次,天真)
I am willing to ignore item #1. It is a corner case that I am willing to document away should I find a viable solution to the other items. Items #2 and #3 can be solved if it were possible to change the metaclass of the copy. I tried (again, naively)
cls_copy = type('cls_copy', cls.__bases__, dict(cls.__dict__),
metaclass=type(cls))
这只是引起了TypeError
的出现,正如预期的那样:
This just raised a TypeError
, as could be expected:
TypeError: __init_subclass__() takes no keyword arguments
根据 docs :
就像其身份一样,对象的类型也是不可更改的. 1
但是,脚注指出
在某些受控条件下,某些情况下 可能会更改对象的类型.不过,通常这不是一个好主意,因为如果处理不当,可能会导致某些非常奇怪的行为.
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.
在什么条件下可以更改对象的类型,特别是类的类型?这是其中一种吗?如果是,怎么办?
What are the conditions under which it is possible to change an object's type, specifically that of a class? Is this one of those cases, and if so, how?
注意
我知道copy.deepcopy
和继承在这里是可行的选择.出于这个问题的目的,我希望忽略这些替代方案,并坚持使用与type
相关的技术.
I am aware that copy.deepcopy
and inheritance are viable alternatives here. For the purpose of this question, I wish to ignore those alternatives and stick with using type
-related techniques.
推荐答案
您可以使用type.__new__(type(cls), cls.__name__, cls.__bases__, dict(cls.__dict__))
.这将使用常规的type
创建过程,但是会创建type(cls)
的实例而不是type
.
You could use type.__new__(type(cls), cls.__name__, cls.__bases__, dict(cls.__dict__))
. This uses the normal type
creation process, but creates an instance of type(cls)
instead of type
.
关于__metaclass__
问题,我认为这是因为__metaclass__
通常是所谓的,所以type
不能使用它.
As for the __metaclass__
issue, I think that is because __metaclass__
is usually what is called, so type
can't use it.
这篇关于是否可以使用type正确复制类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!