【问题标题】:Change object attribute in class method without explicitly naming the attribute在类方法中更改对象属性而不显式命名属性
【发布时间】:2021-07-26 18:39:50
【问题描述】:

我有一个使用python parent child relationship class 构建的类节点。此类定义构建树所需的父/子关系。在我的应用程序中,我正在构建资产负债表。

class Node:
_parent = None

def __init__(self, name='', attributes=None, children=None, parent=None):
    self.name = name
    self.children = children if children is not None else []
    self.parent = parent
    if children is not None:
        for child in children:
            child.parent = self

@property
def parent(self):
    return self._parent() if self._parent is not None else None

@parent.setter
def parent(self, newparent):
    oldparent = self.parent
    if newparent is oldparent:
        return
    if oldparent is not None:
        oldparent.children.remove(self)
    if self not in newparent.children:
        newparent.children.append(self)
    self._parent = weakref.ref(newparent) if newparent is not None else None

我还定义了一个子类 LineItem,用于填充树的节点。当具有给定属性(例如余额)的 LineItem 对象被添加到树中时,我希望添加该属性并将树卷起。例如,如果节点 1 有两个子节点 2 和 3,每个节点的余额分别为 10 和 20,那么节点 1 的余额将为 30。

class LineItem(Node):
def __init__(self, enabled=True, balance=None, native_curr=None, reported_curr='USD', *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.enabled = enabled
    self.balance = balance
    self.currency = native_curr
    self.report_curr = reported_curr
    # propagate the balance up the balance sheet
    super().addrollup(self.balance)

我在类 Node 中创建了一个方法,如果属性始终保持平衡,该方法效果很好。

# propagate the quantity up
def addrollup(self, quantity):
    curr_parent = self.parent
    if quantity is not None:
        while curr_parent is not None:
            if curr_parent.balance is not None:
                curr_parent.balance += quantity
            else:
                curr_parent.balance = quantity
            curr_parent = curr_parent.parent

如果我不想显式调用“余额”,我将如何编写此函数?是否可以编写一个足够通用的函数,它需要一个参数来定义应该汇总什么属性?

【问题讨论】:

  • 你试过重载 setattr 操作符吗?这可以允许设置属性值的通用方法。

标签: python class methods


【解决方案1】:

感谢您对 Željko Jelić 的评论。在查看了 setattrgetattr 之后,我意识到它们可以用于将名称作为参数传递,而不是使用 self.attribute = 语法。

我把函数改写为

    def addrollup(self, attr_name, value):
    curr_parent = self.parent
    if value is not None:
        while curr_parent is not None:
            if getattr(curr_parent, attr_name) is not None:
                setattr(curr_parent, attr_name, getattr(curr_parent, attr_name)+value)
            else:
                setattr(curr_parent, attr_name, value)
            curr_parent = curr_parent.parent

【讨论】:

  • 请注意,使用 setattr 时需要注意不要以无限递归调用结束。例如,使用 dict 来访问属性并重新分配 def __setattr__(self, attr, value): self.__dict__[attr] = value 应该是设置通用属性值的安全方法。当然,您需要根据您的特定问题调整此表格。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-06
  • 2023-03-18
相关资源
最近更新 更多