假设我有一个类,它有许多子类。
我可以实例化这个类。然后我可以将其 __class__
属性设置为子类之一。我已经有效地将类类型更改为其子类的类型,在一个事件对象上。我可以调用它的方法来调用这些方法的子类版本。
那么,这样做有多危险?看起来很奇怪,但这样做是不是错误?尽管能够在运行时更改类型,但这是应该完全避免的语言特性吗?为什么或为什么不?
(根据回复,我将发布一个更具体的问题,说明我想做什么,以及是否有更好的选择)。
最佳答案
以下是我能想到的导致这种危险的事情的 list ,按从最坏到最不坏的粗略顺序排列:
- 阅读或调试您的代码的人可能会感到困惑。
- 您不会获得正确的
__init__
方法,因此您可能不会正确初始化所有实例变量(甚至根本不会)。 - 2.x 和 3.x 之间的差异非常显着,移植起来可能会很痛苦。
- 在类方法、手动编码的描述符、方法解析顺序的 Hook 等方面存在一些极端情况,它们在经典类和新型类之间是不同的(同样,在 2.x 和 3.x 之间)。 x)。
- 如果您使用
__slots__
,则所有类必须具有相同的插槽。 (如果你有兼容但不同的插槽,它可能一开始似乎可以工作,但会做一些可怕的事情......) - 新式类中的特殊方法定义可能不会改变。 (事实上,这在实践中适用于所有当前的 Python 实现,但它没有记录可以工作,所以……)
- 如果你使用
__new__
,事情就不会按照你天真的预期的方式进行。 - 如果类有不同的元类,事情会变得更加困惑。
同时,在您认为有必要这样做的许多情况下,还有更好的选择:
- 使用工厂动态创建适当类的实例,而不是创建基实例,然后将其转换为派生实例。
- 使用
__new__
或其他机制来 Hook 构造。 - 重新设计事物,让您拥有一个具有某些数据驱动行为的类,而不是滥用继承。
作为最后一个最常见的特定情况,只需将所有“变量方法”放入其实例作为“父”的数据成员保存的类中,而不是放入子类中。无需更改 self.__class__ = OtherSubclass
,只需执行 self.member = OtherSubclass(self)
。如果您真的需要神奇地更改方法,那么自动转发(例如,通过 __getattr__
)是一种比动态更改类更常见和 Python 的习惯用法。
关于python - 将 self.__class__ 设置为其他东西有多危险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13280680/