Package: nattrs
nattrsNested attributesutility functions for python. Allows getting/setting of object attributes and dict members interchangeably.
Useful to populate nested dicts for storing outputs of a loop.Alpha stage. Subject to change.https://pypi.python.org/pypi/nattrs/InstallationInstall from pip:pipinstallnattrsInstall from GitHub:python-mpipinstallgit+https://github.com/ludvigolsen/nattrsMain functionsClass/FunctionDescriptionnested_getattrGet object attributes/dict members recursively, given by dot-separated namesnested_setattrSet object attribute/dict member by recursive lookup, given by dot-separated names.nested_mutattrApply function (mutate) to object attribute/dict member by recursive lookup, given by dot-separated names.nested_hasattrCheck whether recursive object attributes/dict members exist.populate_productCreate and populate nested dicts with specified layers and the same leaf value.ExamplesCreate classBwith a dictcwith the memberd:classB:def__init__(self):self.c={"d":1}Add to a dicta:a={"b":B()}nested_getattrGet the value ofd:nested_getattr(a,"b.c.d")>>1Get default value when not finding an attribute:nested_getattr(a,"b.o.p",default="not found")>>"not found"nested_setattrSet the value ofd:nested_setattr(a,"b.c.d",2)Check new value ofd:nested_getattr(a,"b.c.d")>>2nested_mutattrMutatedwith an anonymous function (lambda):nested_mutattr(a,"b.c.d",lambdax:x*5)Check new value ofd:nested_getattr(a,"b.c.d")>>10Note: If your function performs the assignmentin-place, remember to enable theis_inplace_fnargument.nested_hasattrCheck presence of the member 'd':nested_hasattr(a,"b.c.d")>>TrueFail to find member 'o':nested_hasattr(a,"b.o.p")>>Falsepopulate_productIn this example, we wish to pre-populate nested dicts with empty lists to allow appending within aforloop. First, we go through the manual approach of doing this. Second, we show how easy it is to do withpopulate_product().Say we have 3 variables that can each hold 2 values. We want to computesomethingfor each combination of these values. Let's first define these variables and their options:animal=["cat","dog"]food=["strawberry","cucumber"]temperature=["cold","warm"]Let's generate the product of these options:importitertoolscombinations=list(itertools.product(*[animal,food,temperature]))combinations>>[('cat','strawberry','cold'),>>('cat','strawberry','warm'),>>('cat','cucumber','cold'),>>('cat','cucumber','warm'),>>('dog','strawberry','cold'),>>('dog','strawberry','warm'),>>('dog','cucumber','cold'),>>('dog','cucumber','warm')]Now we can create a nested dict structure with a list in the leaf element:# Initialize empty dictnested_dict={}forleafincombinations:# Join each string with dot-separation:attr=".".join(list(leaf))# Assign empty list to the leafs# `make_missing` creates dicts for each# missing attribute/dict membernattrs.nested_setattr(obj=nested_dict,attr=attr,value=[],make_missing=True)nested_dict>>{'cat':{'strawberry':{'cold':[],'warm':[]},>>'cucumber':{'cold':[],'warm':[]}},>>'dog':{'strawberry':{'cold':[],'warm':[]},>>'cucumber':{'cold':[],'warm':[]}}}This dict population is actually provided bypopulate_product(). Instead of an empty list, let's set the value to an "edibility" score that could be changed by a later function:layers=[animal,food,temperature]populate_product(layers=layers,val=False)>>{'cat':{'strawberry':{'cold':False,'warm':False},>>'cucumber':{'cold':False,'warm':False}},>>'dog':{'strawberry':{'cold':False,'warm':False},>>'cucumber':{'cold':False,'warm':False}}}