假设我有一个类,它有许多子类.

我可以实例化这个类.然后我可以将其__class__属性设置为其中一个子类.我已经在一个活动对象上有效地将类类型更改为其子类的类型.我可以在它上面调用调用这些方法的子类版本的方法.

那么,这样做有多危险?这看起来很奇怪,但做这样的事是不是有wrong美元?尽管可以在运行时更改类型,但这是语言中应该完全避免的特性吗?为什么?

(根据回复,我会发布一个更具体的问题,询问我想做什么,以及是否有更好的 Select ).

推荐答案

以下是我能想到的使这件事变得危险的事情 list ,从最坏到最坏的顺序大致如下:

  • 阅读或调试代码的人可能会感到困惑.
  • 您不会得到正确的__init__方法,因此可能不会正确初始化所有实例变量(甚至根本不会).
  • 2.x和3.x的重要性足以使移植时感到痛苦.
  • 有一些带有类方法、手工编码描述符、方法解析顺序挂钩等的边缘情况,它们在classic 类和新型类之间(以及2.x和3.x之间)是不同的.
  • 如果使用__slots__,则所有类都必须具有相同的插槽.(如果你有兼容但不同的插槽,它一开始可能会工作,但会做一些可怕的事情……)
  • 新样式类中的特殊方法定义可能不会更改.(事实上,这在所有当前的Python实现中都是可行的,但这还不是documented个,所以…)
  • 如果你使用__new__,事情就不会按照你天真的预期进行.
  • 如果这些类有不同的元类,事情会变得更加混乱.

同时,在许多你认为有必要这样做的情况下,有更好的 Select :

  • 使用工厂动态创建相应类的实例,而不是创建基实例,然后将其转换为派生实例.
  • 使用__new__或其他机制来钩住 struct .
  • 重新设计东西,这样你就有了一个具有数据驱动行为的单一类,而不是滥用继承.

作为上一种最常见的特殊情况,只需将所有"变量方法"放入类中,这些类的实例作为"父"的数据成员保存,而不是放入子类中.不要改self.__class__ = OtherSubclass,只要改self.member = OtherSubclass(self)就行了.如果你真的需要方法来神奇地改变,那么自动转发(例如,通过__getattr__)是一种比动态改变类更常见、更通俗的习惯用法.

Python-3.x相关问答推荐

使用Python装载. iso文件

如何从Django连接到Neo4J s AuraDB(免费层)?'

在Python中从mySQL获取多行

Pandas 中每行的最大值范围

这是重命名极地df列的最好方式吗?

被多个\n拆分并保留

以编程方式关闭jupyterlab内核

如何确保 GCP Document AI 模型输出与输入文件同名的 JSON?

Pandas matplotlib:条形图占总数的百分比

判断 gekko 中的表达式

集合操作:应该只适用于集合,但适用于 dict_keys?

Await Future 来自 Executor:Future 不能在await表达式中使用

如何为 Python 中的线程设置异步事件循环?

pandas 中 df.reindex() 和 df.set_index() 方法的区别

为 True 相交两个布尔数组

PIL 在图像上绘制半透明方形覆盖

如何判断列表中的所有项目是否都是字符串

python asyncio add_done_callback 与 async def

通过字典有效地替换Pandas 系列中的值

Python:如何在 Windows 资源管理器中打开文件夹(Python 3.6.2、Windows 10)