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

如何在Python Dataclass中利用列表动态设置对象属性?

用Python Dataclass简化重复属性定义与初始化

原代码的冗余问题

原代码中,normal、normalizedNormal、tangent、normalizedTangent这类属性的定义和初始化逻辑大量重复,新增属性时需要修改多处代码:

from dataclasses import dataclass, field


@dataclass
class Locator:
    locator_attr: str
    transform: str = field(init=False)
    position: tuple = field(init=False)
    point_on_curve: str = field(init=False)
    normal_attr: str = field(init=False)
    normal: tuple = field(init=False)
    normalizedNormal_attr: str = field(init=False)
    normalizedNormal: tuple = field(init=False)
    tangent_attr: str = field(init=False)
    tangent: tuple = field(init=False)
    normalizedTangent_attr: str = field(init=False)
    normalizedTangent: tuple = field(init=False)

    def __post_init__(self) -> None:
        self.transform = cmds.listConnections(f"{self.locator_attr}.locatorTransform")[0]
        self.position = cmds.xform(self.transform, q=True, t=True, ws=True)
        self.point_on_curve = cmds.listConnections(f"{self.locator_attr}.pointOnCurve")[0]
        self.normal_attr = f"{self.point_on_curve}.normal"
        self.normal = cmds.getAttr(f"{self.point_on_curve}.normal")[0]
        self.normalizedNormal_attr = f"{self.point_on_curve}.normalizedNormal"
        self.normalizedNormal = cmds.getAttr(f"{self.point_on_curve}.normalizedNormal")[0]
        self.tangent_attr = f"{self.point_on_curve}.tangent"
        self.tangent = cmds.getAttr(f"{self.point_on_curve}.tangent")[0]
        self.normalizedTangent_attr = f"{self.point_on_curve}.normalizedTangent"
        self.normalizedTangent = cmds.getAttr(f"{self.point_on_curve}.normalizedTangent")[0]

尝试动态生成属性时的错误

尝试用列表动态生成属性时,因错误处理列表与dataclass字段的关系,触发两类报错:

  1. 若将列表设为field对象,会抛出'Field' object is not iterable
  2. 若直接用普通列表作为dataclass字段,会抛出mutable default <class 'list'> for field _node_attrs is not allowed: use default_factory

尝试的错误代码:

from dataclasses import dataclass, field

@dataclass
class Locator:
    locator_attr: str
    transform: str = field(init=False)
    position: tuple = field(init=False)
    point_on_curve: str = field(init=False)
    _node_attrs:list = ['normal','normalizedNormal','tangent','normalizedTangent']
    for _attrname in _node_attrs:
        globals()[f'{_attrname}_attr']: str = field(init=False)
        globals()[f'{_attrname}']: tuple = field(init=False)
    def __post_init__(self) -> None:
        self.transform = cmds.listConnections(f"{self.locator_attr}.locatorTransform")[0]
        self.position = cmds.xform(self.transform, q=True, t=True, ws=True)
        self.point_on_curve = cmds.listConnections(f"{self.locator_attr}.pointOnCurve")[
            0
        ]

简洁解决方案

核心思路:将重复属性列表设为类的普通常量(非dataclass字段),避免触发可变默认值检查;同时在类定义阶段动态添加字段,在__post_init__中循环完成属性初始化。

from dataclasses import dataclass, field

@dataclass
class Locator:
    locator_attr: str
    transform: str = field(init=False)
    position: tuple = field(init=False)
    point_on_curve: str = field(init=False)

    # 类常量,不作为dataclass字段(用元组更安全,避免误修改)
    _NODE_ATTRS = ('normal', 'normalizedNormal', 'tangent', 'normalizedTangent')

    def __post_init__(self) -> None:
        self.transform = cmds.listConnections(f"{self.locator_attr}.locatorTransform")[0]
        self.position = cmds.xform(self.transform, q=True, t=True, ws=True)
        self.point_on_curve = cmds.listConnections(f"{self.locator_attr}.pointOnCurve")[0]
        
        # 批量初始化重复属性
        for attr_name in self._NODE_ATTRS:
            full_attr_path = f"{self.point_on_curve}.{attr_name}"
            setattr(self, f"{attr_name}_attr", full_attr_path)
            setattr(self, attr_name, cmds.getAttr(full_attr_path)[0])

# 动态添加字段定义与类型注解
for attr_name in Locator._NODE_ATTRS:
    attr_attr_name = f"{attr_name}_attr"
    # 添加field配置
    setattr(Locator, attr_attr_name, field(init=False))
    setattr(Locator, attr_name, field(init=False))
    # 添加类型注解
    Locator.__annotations__[attr_attr_name] = str
    Locator.__annotations__[attr_name] = tuple

该方案的优势:

  • 新增属性仅需修改_NODE_ATTRS一处
  • 完全消除重复代码逻辑
  • 符合dataclass规范,无报错风险

内容的提问来源于stack exchange,提问作者Vitor Augusto Mariano Silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 18:57:35