You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用非None值的attrs类实例覆盖另一个同类型实例

合并attrs类实例并跳过None值的简洁方案

需求说明

需要合并同一个attrs类的多个实例,用后续实例的非None值覆盖前面实例的对应属性,实现先定义默认值、再按需覆盖的效果。预期效果如下:

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)

# 预期结果:A(a=1, b=3)
instance_3 = merge_instances(instance_1, instance_2)

现有方案优化

你当前的方案可行,但可以通过更简洁、规范的方式实现,以下是几种改进方案:

方案1:用字典推导式简化循环逻辑

直接用字典推导式替代手动循环,代码更紧凑:

from attr import attrs

@attrs(auto_attribs=True)
class A:
    a: int = None
    b: int = None

def merge_instances(instance_1, instance_2):
    merged = {
        key: instance_2.__dict__[key] if instance_2.__dict__[key] is not None else instance_1.__dict__[key]
        for key in instance_1.__dict__
    }
    return A(**merged)

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)  # 输出:A(a=1, b=3)

方案2:使用attrs官方asdict方法(更规范)

避免直接访问__dict__,改用attrs提供的asdict方法获取实例属性字典,更符合官方规范,也能兼容attrs的一些高级配置(比如field的别名):

from attr import attrs, asdict

@attrs(auto_attribs=True)
class A:
    a: int = None
    b: int = None

def merge_instances(instance_1, instance_2):
    dict1 = asdict(instance_1)
    dict2 = asdict(instance_2)
    merged = {k: dict2[k] if dict2[k] is not None else v for k, v in dict1.items()}
    return A(**merged)

方案3:支持多实例合并的通用版本

如果需要合并多个实例(从左到右依次覆盖),可以写一个更通用的版本:

from attr import attrs, asdict

@attrs(auto_attribs=True)
class A:
    a: int = None
    b: int = None

def merge_instances(*instances):
    if not instances:
        raise ValueError("至少需要传入一个实例")
    
    # 以第一个实例的属性为基础
    merged_dict = asdict(instances[0])
    # 依次用后续实例的非None值覆盖
    for inst in instances[1:]:
        current_dict = asdict(inst)
        merged_dict.update({k: v for k, v in current_dict.items() if v is not None})
    
    # 返回同类型的新实例
    return type(instances[0])(**merged_dict)

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)  # A(a=1, b=3)

    # 测试多实例合并
    instance_4 = A(a=4)
    instance_5 = merge_instances(instance_1, instance_2, instance_4)
    print(instance_5)  # A(a=4, b=3)

方案优势

  • 字典推导式让代码更简洁,可读性更强
  • 使用asdict比直接操作__dict__更安全,适配attrs的内部实现变化
  • 多实例版本扩展性更好,能应对更复杂的覆盖场景

内容的提问来源于stack exchange,提问作者Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:45:50