在Python中重新加载模块后进行对象类型转换?【用于动态代码更改】
我正在运行一个交互式的Python会话,这个会话会构建很大的数据结构(超过5GB),加载这些数据结构需要很长时间。因此,我想充分利用Python动态修改代码的能力(虽然有时候我并不想太过计划)。
我现在面临的问题是:我有一个旧的类实例,后来我修改了代码并重新加载了模块——我希望这个旧的实例能够使用新的函数定义。我该怎么做,而不是手动把旧实例的所有信息复制到一个新的实例中呢?
下面是我尝试过的内容。假设我有一个模块M.py
:
class A():
def f(self):
print "old class"
这是一个交互式会话:
import M
old_a = M.a()
# [suppose now I change the definition of M.A.f in the source file]
reload(M)
# I attempt to use the new class definition with the old instance:
M.A.f(old_a)
在这个时候,我收到了Python的一个类型错误:
TypeError: unbound method f() must be called with A instance as first argument (got A instance instead)
显然,Python对接收一个旧的A实例并不满意,尽管在我的代码中它们基本上是功能相同的类型——有没有办法让我把它“转换”成新的实例类型,这样Python就不会抱怨了?就像这样:M.A.f( (M.A) old_a )
?
2 个回答
因为你不能直接转换类型,所以你需要调整你的代码,让这些神秘的“即时代码修改”能够正常工作。
第一步:将算法和数据分开。你需要写一个非常简单(而且不太可能改变)的类来处理原始数据。通常,一个命名元组的列表就足够用了。
第二步:创建一些算法,这些算法在数据对象上“包装”它们,而不是“更新”它们。
像这样。
def some_complex_algo( list_of_named_tuples ):
for item in list_of_named_tuples:
# some calculation
yield NewTuple( result1, result2, ..., item )
现在你可以尝试处理数据了:
result = list( some_complex_algo( source_data ) )
如果你对结果不满意,你只需要重新定义你的 some_complex_algo
并重新运行它。这样 source_data
就不会被改变。实际上,它可以是不可变的。
在Python中没有“类型转换”这个概念,但你可以改变一个已有对象的类。这是完全合法的,而且能达到目的:
old_a.__class__=M.A
old_a.f()
只要你没有改变类的方法和实例变量之间的关系,也没有改动__init__
方法的功能,或者类似的事情,这样做是没问题的。
补充说明:正如jsbueno
所提到的,当你改变__class__
的时候,__init__
或__new__
方法并不会被调用。此外,新的__del__
方法会在对象被销毁时被调用。