I agree that the supplied code is improvable. Consider this:<p><pre><code> def set_r(adict, keypath, val):
key = keypath[0]
if len(keypath) == 1:
adict[key] = val
return
if not key in adict:
adict[key] = {}
set_r(adict[key], keypath[1:], val)
def build_book_inventory(book_ids, shops):
shop_labels = [shop['label'] for shop in shops]
books = Persistency_books_table_read(
shop_labels=shop_labels,
book_ids=book_ids)
inventory = {}
keys = 'shop_label cell_label book_id'.split()
for book in book_list:
keypath = [book[k] for k in keys]
set_r(inventory, keypath, book['count']
return inventory
</code></pre>
First, the author clearly needed "autovivification" as supplied by Perl. We supply a substitute with set_r().<p>Second, I'd avoid creating local variables like "book_id". It creates mess. We never had the slightest interest in the book_id; it's just part of the wine we are pouring from one bottle into another.<p>Third, I've preserved (modulo names) the interface of this function but I suspect the surrounding code could also be improved. Also call a list of books "books", not book_list; list is the assumed sequence container in Python. "books=book_ids" is unfortunate; to thrive in a weakly typed language we need variable names that distinguish objects from ids.<p>Larger point: the author wants to create classes for the various business objects, which is a common enough pattern, but ultimately just makes extra work and redundant lines of code. A relational database can handle a wide variety of objects, with some knowledge of their semantics, without any custom code per-class.<p>As you know, the difference between dicts and objects in python is mostly semantic sugar. We can easily enough make a class that gives dot-notation access to values in a dict, if one objects to the noisiness of foo['bar'].<p>If you want to enforce object schema at system boundaries, there are better ways (more compact, expressive and maintainable) than writing elaborate "classes" for each type of object.