I'm creating a data structure with nested namedtuples (practicing my immutable functional programming skills), but am struggling to find an easy way to replace values in nested namedtuples.
Let's say I have a data structure like this:
from collections import namedtuple
Root = namedtuple("Root", "inventory history")
Inventory = namedtuple("Inventory", "item1 item2")
Item = namedtuple("Item", "name num")
Event = namedtuple("Event", "action item num")
r = Root(
inventory=Inventory(
item1=Item(name="item1", num=1),
item2=Item(name="item2", num=2)
),
history=(
Event(action="buy", item="item1", num=1),
Event(action="buy", item="item2", num=2)
)
)
# Updating nested namedtuples is very clunky
num_bought = 4
r_prime = r._replace(
history = r.history + (Event(action="buy", item="item2", num=num_bought),),
inventory = r.inventory._replace(
item2 = r.inventory.item2._replace(
num = r.inventory.item2.num + num_bought
)
)
)
# Contrast with the ease of using a version of this based on mutable classes:
r.history += Event(action="buy", item="item2", num=num_bought),
r.inventory.item2.num += num_bought
As you can see, changing the value for an item in the inventory is quite a pain, thanks to a) being forced to individually update all of the layers the value is nested under, and b) not having access to operators like +=
.
This gets even uglier if the item in my inventory I'm updating is dynamic, thanks to calls to getattr
being strewn everywhere.
Is there an easier way to handle this?