遍历Python对象树
我试图在Python中实现动态重载对象,以实时反映代码更改 重新加载模块是可行的,但我必须重新创建模块类的每个实例,以使更改生效 问题是对象数据(对象遍历Python对象树,python,reload,traversal,Python,Reload,Traversal,我试图在Python中实现动态重载对象,以实时反映代码更改 重新加载模块是可行的,但我必须重新创建模块类的每个实例,以使更改生效 问题是对象数据(对象\uuuuuu dict\uuuuu内容)在该过程中丢失 所以我尝试了另一种方法: def refresh(obj, memo=None): if memo is None: memo = {} d = id(obj) if d in memo: return memo[d] = No
\uuuuuu dict\uuuuu
内容)在该过程中丢失
所以我尝试了另一种方法:
def refresh(obj, memo=None):
if memo is None:
memo = {}
d = id(obj)
if d in memo:
return
memo[d] = None
try:
obj.__class__ = getattr(sys.modules[obj.__class__.__module__],
obj.__class__.__name__)
except TypeError:
return
for item in obj.__dict__.itervalues():
if isinstance(item, dict):
for k, v in item.iteritems():
refresh(k, memo)
refresh(v, memo)
elif isinstance(item, (list, tuple)):
for v in item:
refresh(v, memo)
else:
refresh(item, memo)
令人惊讶的是,它的工作!对我的对象调用refresh()后,新代码将生效,而无需重新创建它们
但我不确定这是不是穿越物体的正确方法?有没有更好的方法来遍历对象的组件?请参阅Python Cookbook(或者更好的版本是“打印”版本,我相信您可以通过google book search免费阅读,或者在O'Reilly的“Safari”上阅读网站使用免费1周试用订阅——我对哈德逊的原始配方做了大量编辑,以获得“印刷本”版本!)。请参见Python烹饪书(或者更好的是,它的“印刷本”版本,我相信你可以通过谷歌图书搜索免费阅读,或者在O'Reilly的“Safari”上阅读使用免费1周试用订阅的站点——我对Hudson的原始配方进行了大量编辑以获得“印刷书籍”版本!)。这与我采用的解决方案非常相似(一些“顶级”类被包装并跟踪其实例以允许重新加载它们)。问题是,我不想包装包中的所有类(或者像您的示例中那样从重新加载的类继承),只想包装顶级类。这就是为什么我需要一个对象树遍历函数的原因。我相信你不能完全通用地做到这一点——根据插槽和其他元类功能的不同,Python对象可能被编码为根本不支持这一点(这就是为什么在编写扩展代码时,需要为垃圾收集遍历、weakrefs、pickling/unpickling和c提供特定支持的原因)。打开文件、DB连接、生成器对象、锁等。如果您愿意冒丢失某些部分的风险,请确保至少覆盖集合、DEQUE、defaultdicts的默认\u工厂成员等。好的,那么我只需在我的迭代开关中添加更多类型测试。如果有某种has\u序列\u接口/has\u映射\u接口,那就太好了()函数来测试对象的迭代方式。这与我采用的解决方案非常相似(一些“顶级”类被包装并跟踪它们的实例以允许重新加载它们)。问题是我不想包装包中的所有类(或从重新加载的类继承,如您的示例所示),只是顶级的。这就是为什么我需要一个对象树遍历函数。我相信你不能用完全的通用性来完成它——根据插槽和其他元类功能,Python对象可能被编码为根本不支持它(这就是为什么在编写扩展代码时,需要为垃圾收集遍历、weakrefs、pickling/unpickling和c提供特定支持的原因)。打开文件、DB连接、生成器对象、锁等。如果您愿意冒丢失某些部分的风险,请确保至少覆盖集合、DEQUE、defaultdicts的默认\u工厂成员等。好的,那么我只需在我的迭代开关中添加更多类型测试。如果有某种has\u序列\u接口/has\u映射\u接口,那就太好了()函数用于测试对象的迭代方式。