如何创建与另一个对象相同类的新实例?

12 投票
1 回答
9090 浏览
提问于 2025-04-16 04:18

假设你有一个对象 x,它是某个类的实例。现在你想创建一个和 x 一样类型的新实例,但又不想导入所有可能的类,也不想用 isinstance 来判断类型该怎么做。

比如说,如果 x 是一个小数:

>>> from decimal import Decimal
>>> x = Decimal('3')
>>> x
Decimal('3')

那么你该怎么创建一个新的 Decimal 实例呢?我觉得比较明显的做法是这样:

>>> type(x)('22')
Decimal('22')
>>> x.__class__('22')
Decimal('22')

但是要注意,__class__int 上是不能用的:

>>> 1.__class__
  File "<stdin>", line 1
    1.__class__

那么使用 type 来实现这个目标是否是个好主意?或者说还有其他方法,或者在使用这种方法创建新对象时需要注意什么?

注意: 之前有一个回答被删掉了,里面提到了一种正确的方法来获取 int__class__

>>> (1).__class__
<type 'int'>

使用场景

这个问题主要是理论上的,但我现在在用 Qt 的时候正好用到了这种方法来创建新的 QEvent 实例。比如说,QEvent 对象会被应用程序的事件处理器消耗,以便将事件发送到 QStateMachine。如果不创建事件的新实例,就会出现运行时错误,因为底层的 C++ 对象会被删除。

而且因为我使用的是自定义的 QEvent 子类,它们都共享同一个基类,所以这些对象接受相同的一组预定义参数。

1 个回答

12

调用 type(x) 确实是创建一个和 x 完全相同类型的新实例的标准方法。不过,传给这个调用的参数并不是固定的,因为不同类型的“签名”(也就是需要传入的参数数量和类型)是不同的;所以,如果你对类型一无所知,就需要更多的检查来确定该传什么参数(还有一些规则或经验法则来决定你想传哪些参数,比如你可能需要传0到3个参数,且可选的/关键字参数的名字是'y'、'z'、't'……显然,在这里建立一个通用的规则是不可能的!)。

所以,请你澄清一下(当要实例化的类型很容易确定时;-))你打算如何处理你问题中那些困难的部分,而你甚至没有提到?你能对类型的签名做出什么假设?你需要对这些进行一些合理性检查吗,还是说直接因为传入错误类型或数量的参数导致 TypeError 是可以接受的?等等……没有更多这方面的信息,你的问题就很难得到一个在现实中可以使用的答案!-)

撰写回答