【发布时间】:2026-02-23 21:30:01
【问题描述】:
一般 Python 问题
我正在导入一个具有以下类结构的 Python 库(称为 animals.py):
class Animal(object): pass
class Rat(Animal): pass
class Bat(Animal): pass
class Cat(Animal): pass
...
我想为每个物种类(Rat,Bat,Cat,...)添加一个父类(Pet);但是,我无法更改要导入的库的实际来源,因此它必须是运行时更改。
以下似乎有效:
import animals
class Pet(object): pass
for klass in (animals.Rat, animals.Bat, animals.Cat, ...):
klass.__bases__ = (Pet,) + klass.__bases__
这是在 Python 中将父类注入继承树而不修改要修改的类的源定义的最佳方法吗?
激励环境
我正在尝试将持久性移植到控制实验室设备的大型库中。与它混为一谈是不可能的。我想试试 ZODB 的Persistent。我不想编写 mixin/facade 包装库,因为我正在处理 100 多个类和需要更新的应用程序代码中的大量导入。我正在通过仅在我的入口点上进行黑客攻击来测试选项:设置数据库,如上所示进行修补(但在动物模块上通过自省而不是显式列出来拉取物种类),然后在我退出时关闭数据库。
Mea Culpa / 请求
这是一个故意笼统的问题。我对注入父母和 cmets 的不同方法感兴趣,这些方法的优缺点。我同意这种运行时的诡计会让代码变得非常混乱。如果我选择 ZODB,我会做一些明确的事情。目前,作为 python 的普通用户,我对一般情况感到好奇。
【问题讨论】:
-
不要这样做。如果你真的不能修改导入的模块,如果你真的可以写一个新的父类,你至少必须能够看到它,所以你不能在你的模块中简单地重新实现它们吗?如果没有,尽可能创建使用
Pet作为mixin 的子类——class PetRat(Pet, Rat): pass。几乎可以肯定你不应该在运行时这样做,还有 另一种方法。 -
@agf 该库由第三方支持。复制/粘贴重新实现不是一个好的长期解决方案。我认为通过混合 Pet 来创建 PetXats 的包装库会更好;然而,正如我在编辑中所说,这主要是一个学术/python 内部问题。
-
我认为你已经概述了“方法”,而不是实际阅读库模块,用正则表达式重写它,然后编译它。
-
@agf:
class Blah(Mixin, Main): pass比动态插入新的父级更好吗?
标签: python oop inheritance monkeypatching