假设您有一个从模块内的类实例化的对象。现在,重新加载该模块。您想要做的下一件事是使重载影响该类。
mymodule.py
---
class ClassChange():
def run(self):
print 'one'
myexperiment.py
---
import mymodule
from mymodule import ClassChange # why is this necessary?
myObject = ClassChange()
myObject.run()
>>> one
### later, i changed this file, so that it says print 'two'
reload(mymodule)
# trick to change myObject needed here
myObject.run()
>>> two您是否必须创建一个新的ClassChange对象,将myObject复制到该对象中,然后删除旧的myObject?或者有没有更简单的方法?
Edit: run()方法看起来像是一种静态的类样式方法,但这只是为了简洁。我希望run()方法对对象内部的数据进行操作,因此静态模块函数不能...
发布于 2009-07-03 21:59:28
要更新一个类的所有实例,有必要跟踪这些实例的某个位置--通常通过弱引用(弱值dict是最方便和通用的),所以“跟踪”功能当然不会阻止不需要的实例消失!
您通常希望在类对象中保留这样一个容器,但在本例中,由于您将重新加载模块,因此获取旧的类对象并不是一件容易的事;在模块级工作会更简单。
因此,假设一个“可升级模块”需要在一开始定义一个弱值dict (和一个辅助的"next key to use“int),比如说,使用传统名称:
import weakref
class _List(list): pass # a weakly-referenceable sequence
_objs = weakref.WeakValueDictionary()
_nextkey = 0
def _register(obj):
_objs[_nextkey] = List((obj, type(obj).__name__))
_nextkey += 1模块中的每个类都必须有一个用于注册新实例的调用_register(self) (通常在__init__中)。
现在,“重新加载函数”可以在重新加载模块之前通过获取_objs的副本来获取此模块中所有类的所有实例的花名册。
如果所需要的只是更改代码,那么生活就相当简单:
def reload_all(amodule):
objs = getattr(amodule, '_objs', None)
reload(amodule)
if not objs: return # not an upgraable-module, or no objects
newobjs = getattr(amodule, '_objs', None)
for obj, classname in objs.values():
newclass = getattr(amodule, classname)
obj.__class__ = newclass
if newobjs: newobjs._register(obj)遗憾的是,人们通常确实希望给新类一个机会来更精细地将旧类的对象升级到自身,例如通过合适的类方法。这也不是太难:
def reload_all(amodule):
objs = getattr(amodule, '_objs', None)
reload(amodule)
if not objs: return # not an upgraable-module, or no objects
newobjs = getattr(amodule, '_objs', None)
for obj, classname in objs:
newclass = getattr(amodule, classname)
upgrade = getattr(newclass, '_upgrade', None)
if upgrade:
upgrade(obj)
else:
obj.__class__ = newclass
if newobjs: newobjs._register(obj)例如,假设新版本的类Zap已将一个属性从foo重命名为bar。这可能是新Zap的代码:
class Zap(object):
def __init__(self):
_register(self)
self.bar = 23
@classmethod
def _upgrade(cls, obj):
obj.bar = obj.foo
del obj.foo
obj.__class__ = cls这还不是全部--关于这个主题还有很多要说的--但是,这是要点,答案已经足够长了(我已经够累了;)。
发布于 2009-07-03 20:04:49
你必须创建一个新的对象。没有办法神奇地更新现有的对象。
阅读reload builtin documentation -它非常清楚。下面是最后一段:
如果模块实例化类的实例,则重新加载定义该类的模块不会影响实例的方法定义-它们将继续使用旧的类定义。派生类也是如此。
文档中还有其他警告,所以您真的应该阅读它,并考虑替代方案。也许你想从开始一个新的问题,为什么你想要使用reload,并询问实现相同功能的其他方法。
发布于 2012-04-04 05:58:55
我的方法如下:
这种方法的优点是:
您可以在此处阅读有关该技术(及其局限性)的信息:http://luke-campagnola.blogspot.com/2010/12/easy-automated-reloading-in-python.html
你可以在这里下载代码:http://luke.campagnola.me/code/downloads/reload.py
https://stackoverflow.com/questions/1080669
复制相似问题