无法修改函数时,如何将其返回对象转为子类实例并继承属性?
解决方法:将
bar()返回的实例属性转移到Foo实例 嘿,这问题很常见!你需要把bar()返回的Something实例的状态(属性)转移到Foo实例上,同时保留Foo自身的方法,又不能修改bar函数对吧?下面给你两种实用的方案,按需选择:
方案一:直接合并实例属性字典
最简单的方式就是在Foo的构造函数里,把传入的Something实例的属性直接复制到当前Foo实例中。Python的实例属性大多存在__dict__字典里,我们可以直接用update方法合并:
class Something: def create(self): print('Creating') class Foo(Something): def __init__(self, something_instance, *args, **kwargs): # 先完成父类的初始化 super().__init__(*args, **kwargs) # 把传入的Something实例的属性合并到当前Foo实例 self.__dict__.update(something_instance.__dict__) def do_something(self): print('Do something') def bar(): # 无法修改此函数 return Something() # 测试一下 s = bar() # 给s加个自定义属性模拟实际场景中的状态 s.custom_data = "I'm from the bar() instance" f = Foo(s) f.create() # 输出: Creating f.do_something() # 输出: Do something print(f.custom_data)# 输出: I'm from the bar() instance
优点:简单直接,属性复制后就属于Foo实例自己了,后续修改f的属性不会影响原s实例。
注意:如果Something用了__slots__定义属性(没有__dict__),这种方法就不适用,需要单独处理每个属性。
方案二:动态代理(转发属性访问)
如果你不想复制属性,而是想让Foo实例动态“借用”原Something实例的属性,可以用__getattr__方法做代理。这个方法会在实例找不到对应属性/方法时自动触发,我们把请求转发给原实例就行:
class Something: def create(self): print('Creating') class Foo(Something): def __init__(self, something_instance, *args, **kwargs): super().__init__(*args, **kwargs) # 保存原实例的引用 self._original_something = something_instance def do_something(self): print('Do something') # 转发未找到的属性/方法到原实例 def __getattr__(self, name): return getattr(self._original_something, name) def bar(): return Something() s = bar() s.dynamic_attr = "Proxy works!" f = Foo(s) f.create() # 输出: Creating f.do_something() # 输出: Do something print(f.dynamic_attr)# 输出: Proxy works!
优点:不用复制属性,原实例的属性变化会实时反映到Foo实例上;适合属性动态更新的场景。
注意:Foo自身或继承的属性/方法会优先被调用,只有找不到的才会转发,这正好符合你的需求。
内容的提问来源于stack exchange,提问作者Andrew Graham-Yooll
相关产品推荐
相关产品推荐

