![](/img/trans.png)
[英]Python: Is it possible to override/extend an instance method of one class when it is used in another class?
[英]How to override an attrs class instance with another one when the values are not None
我的目標是能夠合並相同attrs
class 的多個實例並跳過“無”值。
這允許我創建默認值,然后在需要時覆蓋它們。
預期代碼的示例-
from attr import attrs
@attrs(auto_attribs=True)
class A:
a: int = None
b: int = None
instance_1 = A(a=1, b=2)
instance_2 = A(b=3)
# Expected result
instance_3 = merge_instances(instance_1, instance_2)
# instance_3 = A(a=1, b=3)
我目前找到的最佳解決方案如下 -
from attr import attrs
@attrs(auto_attribs=True)
class A:
a: int = None
b: int = None
def merge_instances(instance_1, instance_2):
dict_1 = instance_1.__dict__
dict_2 = instance_2.__dict__
new_values = {}
for key in dict_1:
new_values[key] = dict_2[key] if dict_2[key] is not None else dict_1[key]
return A(**new_values)
if __name__ == '__main__':
instance_1 = A(a=1, b=2)
instance_2 = A(b=3)
instance_3 = merge_instances(instance_1, instance_2)
print(instance_3)
哪種感覺像黑客。 如果有人有更簡單的解決方案,我很想聽聽!
這個更干凈
def merge_instances(instance_1, instance_2):
dict_1 = instance_1.__dict__
dict_2 = instance_2.__dict__
new_values = {k: dict_2[k] or dict_1[k] for k in dict_1}
return A(**new_values)
由於此 function 與 class A
嚴格相關,因此您可以將其設為類方法
from attr import attrs
@attrs(auto_attribs=True)
class A:
a: int = None
b: int = None
@classmethod
def merge_instances(cls, instance_1, instance_2):
dict_1 = instance_1.__dict__
dict_2 = instance_2.__dict__
return cls(
**{k: dict_2[k] or dict_1[k] for k in dict_1}
)
if __name__ == '__main__':
instance_1 = A(a=1, b=2)
instance_2 = A(b=3)
instance_3 = A.merge_instances(instance_1, instance_2)
由於您已經在使用 attrs,因此這更慣用:
from attrs import define, fields
@define
class A:
a: int = None
b: int = None
instance_1 = A(a=1, b=2)
instance_2 = A(b=3)
def merge_instances(i1: A, i2: A) -> A:
kw = {}
for f in fields(A):
v = getattr(i2, f.name)
kw[f.name] = v if v is not None else getattr(i1, f.name)
return A(**kw)
assert A(a=1, b=3) == merge_instances(instance_1, instance_2)
另一種可能更長,但對我來說感覺更干凈的可能性是使用attrs.evolve()
:
def merge_instances(i1: A, i2: A) -> A:
kw = {}
for f in fields(A):
v = getattr(i2, f.name)
if v is not None:
kw[f.name] = v
return evolve(i1, **kw)
如果你能使用海象就更好了:
def merge_instances(i1: A, i2: A) -> A:
kw = {}
for f in fields(A):
if (v := getattr(i2, f.name)) is not None:
kw[f.name] = v
return evolve(i1, **kw)
這可以進一步簡化:
def merge_instances(i1: A, i2: A) -> A:
return evolve(
i1,
**{
f.name: v
for f in fields(A)
if (v := getattr(i2, f.name)) is not None
},
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.