Reputation: 21
I have a class Node that I built using python parent child relationship class. This class defines the parent/children relationship needed to build a tree. In my application, I am building a balance sheet.
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
I also define a subclass LineItem that I use to populate the nodes of my tree. When a LineItem object with a given attribute (e.g. balance) gets added to the tree, I would like that attribute to be added and rolled up the tree. For example, if node 1 has two children node 2 and 3 with each a balance of 10 and 20 respectively, then Node 1 would get a balance of 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)
I created a method in the class Node that works well if the attribute is always balance.
# 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
How would I write this function if I didn't want to explicitly call out "balance"? Is it possible to write a function generic enough that it takes an argument to define what attribute should be rolled up?
Upvotes: 1
Views: 215
Reputation: 21
Thank you for your comment Željko Jelić. After looking at setattr and getattr, I realized that they could be used to pass the name as an argument instead of using the self.attribute = syntax.
I rewrote the function as
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
Upvotes: 1