Search code examples
python-3.xkeyword-argumentanytree

accessing **kwargs in anytree nodes


I'm new to Python/AnyTree and am trying to get a list of raw ingredients to make a bunch of Harburgers (Hamburgers at Point San Pablo Harbor near San Francisco - you need to check it out if you're in the area!! In fact, the winning answer here gets a free Harburger on me next time you're in town!) But I digress...

The question is how can I get access to the 'qty' and 'uom' fields in the tree?

from anytree import Node, RenderTree, PreOrderIter
Harburger=Node("Harburger", children=[
        Node("RoundRoll", qty=1, uom='ea'),
        Node("GriddleGhee", qty = 1, uom='gm'),
        Node("SmashedBurger", qty = 5, uom='oz')])

print(RenderTree(Harburger))

Node('/Harburger')
├── Node('/Harburger/RoundRoll', qty=1, uom='ea')
├── Node('/Harburger/GriddleGhee', qty=1, uom='gm')
└── Node('/Harburger/SmashedBurger', qty=5, uom='oz')

So far, so good. Now I can traverse the tree, like:

#print ingredients for 5 Harburgers
print([(node.name for node in PreOrderIter(Harburger)])

['Harburger', 'RoundRoll', 'GriddleGhee', 'SmashedBurger']

How can I modify this command to get qty and uom?

I've tried

print([(node.name, node.qty) for node in PreOrderIter(Harburger)])

only to get errors!


Solution

  • The issue your code accessing the extra attributes has is that the top-level Node doesn't have the qty and uom attributes, so when it comes up first in the pre-order tree traversal, the code quits with an exception.

    You can fix this in a few ways. One way, which you've commented has worked, is to add the attributes to the root node too.

    Another option might be to test for the attributes before using them, with something like:

    print([(node.name, node.qty) for node in PreOrderIter(Harburger) if hasattr(node, "qty")])
    

    If you can rely upon your tree only having the two levels (the top-level root node and its children), you can iterate over just the child nodes instead of doing a full traversal. Just use Harburger.children rather than PreOrderIter(Harburger).