我发现自己陷入了困境,我开发了一个类,然后我创建了这个类的实例。这些类通常会执行数据和统计操作,这需要很长时间,有时需要 20 分钟。
我将继续开发我的类,并向其添加其他方法。现在,如何使用新方法更新以前的类实例,而无需重新初始化类的旧实例,在这种情况下需要 20 分钟?
这里有一个XY问题。 你真正的困难似乎是"__init__
需要 20 分钟才能完成"。
有几种办法可以摆脱这种困境。
- 花几分钟时间计算一个新实例,然后安排将其快速序列化到磁盘。如果反序列化时间不到二十分钟,你就赢了!
- 使用间接寻址级别,因此具有如此多有趣行为的对象是轻量级的,消耗很少的内存。让它包含指向 RDBMS ID、S3 存储桶、URL 或文件名的指针。
- 将昂贵的对象存储在全局或等效对象中,例如使用
@lru_cache
,并让您更新/重新加载的类以这种方式找到它。使用importlib.reload()
. - 与序列化类似,提供便宜的 .copy() 并利用继承。
- 猴子补丁。
这是利用继承的一种方法 (复制不是必需的,但会使其更干净):
class FooBase:
...
# global variable for expensive computation
foo = FooBase()
class FooFeature(FooBase):
def __init__(self, foo):
...
def some_new_feature(self):
...
foo = FooFeature(foo.copy()) # This happens quickly.
这是猴子补丁的一种方法:
class Foo:
...
foo = Foo()
FooOriginal = Foo
# Now you edit in a brand new Foo feature and reload the class definition:
def new_feature(self):
...
FooOriginal.new_feature = Foo.new_feature
猴子打补丁时, 请注意,foo
包含对FooOriginal
包含的同一类对象的引用。 重新加载后,Foo
变成一个全新的对象, 使用一种附加方法。 最后的猴子补丁作业 使该方法可用于FooOriginal
, 因此可供foo