在Jupyter中通过已有实例Monkey Patching类的方法与属性
需求:无需重新初始化耗时实例,自动更新已有类实例的方法与属性
在Jupyter做项目原型开发时,希望不用手动修改类或重新初始化耗时的实例,就能自动给已有类实例添加/删除方法与属性。举个例子:
class A(object): def __init__(self): # 耗时的初始化操作 def keep_this_fxn(self): return 'hi' a = A() # 现在想把A升级成A_new class A_new(object): def __init__(self, v): # 同样耗时的初始化操作 self._new_prop = v def keep_this_fxn(self): return 'hi' @property def new_prop(self): return self._new_prop def new_fxn(self): return 'hey'
希望不用手动执行A.new_fxn = A_new.new_fxn或者重新初始化实例,就能自动完成这类更新。比如实现一个update_instance函数,达到以下效果:
def update_instance(a, new_instance): # 实现逻辑在这里? # 调用时不能像原初始化那样慢! a = update_instance(a, A_new(5)) >>> type(a) # 最好保持原类名 <A> >>> a.keep_this_fxn() # 保留原方法功能 'hi' >>> a.new_fxn() # 新增方法可用 'hey' >>> a.new_prop # 新增属性可用 5
之前查过相关帖子,但都没覆盖这种场景(尤其是新增属性和参数的情况)。
当前尝试的代码:
def update_class_instance(instance, NewClass, new_method_list): OrigClass = type(instance).__mro__[0] for method in new_method_list: setattr(OrigClass, method, getattr(NewClass, method))
但存在两个问题:
- 必须手动指定
new_method_list,希望能自动识别新增的方法 - 不知道如何处理新增的属性和参数
解决方案
要实现这个需求,我们可以从实例属性拷贝和类动态补丁两方面入手:
1. 自动识别新旧类的差异
通过对比原类与新类的成员,自动找出新增/修改的方法、特性(@property),同时从新实例中提取新增的实例属性,无需手动指定列表。
2. 实现update_instance函数
def update_instance(original_instance, new_instance): orig_cls = type(original_instance) new_cls = type(new_instance) # 处理类层面的方法和特性 orig_members = {k: v for k, v in orig_cls.__dict__.items() if not k.startswith('__')} new_members = {k: v for k, v in new_cls.__dict__.items() if not k.startswith('__')} # 新增/更新类方法与特性 for name, member in new_members.items(): if name not in orig_members or member != orig_members[name]: setattr(orig_cls, name, member) # 处理实例层面的属性(从新实例拷贝新增属性) new_instance_attrs = {k: v for k, v in new_instance.__dict__.items() if k not in orig_cls.__dict__} for attr_name, attr_value in new_instance_attrs.items(): setattr(original_instance, attr_name, attr_value) # 可选:删除原类中被移除的成员 # for name in orig_members: # if name not in new_members: # delattr(orig_cls, name) return original_instance
3. 使用示例
# 原实例初始化 a = A() # 创建新实例(仅执行一次耗时初始化) new_a = A_new(5) # 更新原实例 a = update_instance(a, new_a) # 验证效果 print(type(a)) # <class '__main__.A'> print(a.keep_this_fxn()) # 'hi' print(a.new_fxn()) # 'hey' print(a.new_prop) # 5
关键说明
- 类层面的修改是全局的:所有
A类的实例都会被更新,适合原型开发场景 - 实例属性直接从新实例拷贝,避免重复执行耗时初始化
- 自动识别新增的方法和特性,无需手动指定列表
- 如果仅需更新单个实例而非全局类,可修改为直接给实例绑定方法(但特性只能绑定到类)
内容的提问来源于stack exchange,提问作者irene
相关产品推荐
相关产品推荐

