是否可以使用type正确复制类 [英] Is it possible to properly copy a class using type

查看:60
本文介绍了是否可以使用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:

  1. 由未最终调用type.__new__的元类创建的__dict__的类型可能与通常的代理对象不同.
  2. 扩展副本的类将没有正确的元类,这可能会导致意外行为.
  3. 在原始元类中定义的任何属性或其他数据描述符将不再在类对象上可用.
  1. The __dict__ created by metaclasses that do not end up calling type.__new__ may be of a different type than the usual proxy object.
  2. Classes extending the copy will not have the correct metaclass, which may cause unexpected behavior.
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆