python dictionary update methods to extend dictionary - python

So i am using dictionary within a dictionary and every time I would try to extend the child_dict, which i do using a loop, only the last iteration value persists while the previous ones are over-written
parent_dict = defaultdict(list)
for getdata from datasource:
# I generate 'child_dict' here
parent_dict[parentDict_key] = child_dict
I tried to use .update(child_dict) method but it gives me
AttributeError: 'list' object has no attribute 'update'
I also tried to use .append() method but it makes the parent a list of dictionaries.
Is there any better way to add new child_dict to my parent_dict and just extend it during each iteration?

Well, if you want your values to be dictionaries and not lists you should use:
parent_dict = defaultdict(dict)
instead of:
parent_dict = defaultdict(list)
and then to generate:
parent_dict[parentDict_key][child_dict_key] = child_dict_value

Related

How to loop through an object attribute with list comprehension?

I have a list - list_of_objects = [<obj1>,<obj2>]. Each object has an attribute <ob1j>.content. Each content attribute holds a list of dictionaries [{"key":"value"}, {"key":"value"}]. How do I use list comprehension to "unpack" these dictionaries into a single list? Example that doesn't work:
list_of_dictionaries = [dict for obj in list_of_objects for item in obj.content]
Basically I want to turn the below loop that works into a comprehension:
for obj in list_of_objects:
new_list.extend(obj.content)
Calling dir on the object gives you back all the attributes of that object, including python special attributes.You can always filter out the special methods by using a list comprehension.

Python Dictionary Object Instantiation NameError

I am making a console application that can load different dictionaries filled with Spanish words and definitions, my thinking here is that I want to make all the objects of my Dictionary class in this module and then import them via one dict_of_dicts into main.py. Instead of writing out each instantiating each individual object like so:
animals_dict = Dictionary('animals')
I wanted to loop through my dict_of_dicts and create them. Now when I do this I get a NameError because these objects are not yet defined, which makes sense I suppose, but I was wondering if there is a work around here to make these objects by a loop instead of just writing them out one by one.
# list of dictionaries loaded into main.py at runtime
from dict_class import Dictionary
dict_of_dicts = {'animals':animals_dict, 'nature':nature_dict, 'irregulars':irregulars_dict,
'clothes':clothes_dict, 'foodbev':foodbev_dict, 'phrases':phrases_dict,
'verbs':verbs_dict,'adjectives':adjectives_dict,'future':future_dict,'past':past_dict,
'wotd':wotd_dict}
for k,v in dict_of_dicts:
v = Dictionary(k) #k=self.name
print(v) #v=object
Suppose you have a list of names ['animals', 'nature', 'irregulars'] #etc
You can loop over that to create a new dictionary
my_dicts = {}
names = ['animals', 'nature', 'irregulars']
for name in names:
my_dicts[name] = Dictionary(name)
Or as a comprehension
my_dicts = {name: Dictionary(name) for name in names}
Besides the object not existing yet, the other problem you would run into is that when looping over a dictionary's items through dict.items, making an assignment on that name will not actually modify the dictionary.
for key, value in some_dict.items():
value = 'new' # Bad. Does not modify some_dict
for key in some_dict:
some_dict[key] = 'new' # Good. Does modify some_dict
names = ['animals', 'nature', 'foodbev'] # dict's names
dict_of_dicts = {}
for name in names:
dict_of_dicts[name] = Dictionary(k)

Python : AttributeError: 'int' object has no attribute 'append'

I have a dict of int, list. What I'm trying to do is loop through `something' and if the key is present in the dict add the item to the lsit or else create a new list and add the item.
This is my code.
levels = {}
if curr_node.dist in levels:
l = levels[curr_node.dist]
l.append(curr_node.tree_node.val)...........***
else:
levels[curr_node.dist] = []
levels[curr_node.dist].append(curr_node.tree_node.val)
levels[curr_node.dist] = curr_node.tree_node.val
My question is two-fold.
1. I get the following error,
Line 27: AttributeError: 'int' object has no attribute 'append'
Line 27 is the line marked with ***
What am I missing that's leading to the error.
How can I run this algorithm of checking key and adding to a list in a dict more pythonically.
You set a list first, then replace that list with the value:
else:
levels[curr_node.dist] = []
levels[curr_node.dist].append(curr_node.tree_node.val)
levels[curr_node.dist] = curr_node.tree_node.val
Drop that last line, it breaks your code.
Instead of using if...else, you could use the dict.setdefault() method to assign an empty list when the key is missing, and at the same time return the value for the key:
levels.setdefault(curr_node.dist, []).append(curr_node.tree_node.val)
This one line replaces your 6 if: ... else ... lines.
You could also use a collections.defaultdict() object:
from collections import defaultdict
levels = defaultdict(list)
and
levels[curr_node.dist].append(curr_node.tree_node.val)
For missing keys a list object is automatically added. This has a downside: later code with a bug in it that accidentally uses a non-existing key will get you an empty list, making matters confusing when debugging that error.

How can I associate a dict key to an attribute of an object within a list?

class SpreadsheetRow(object):
def __init__(self,Account1):
self.Account1=Account1
self.Account2=0
I have a while loop that fills a list of objects ,and another loop that fills a dictionary associating Var1:Account2. But, I need to get that dictionary's value into each object, if the key matches the object's Account1.
So basically, I have:
listofSpreadsheetRowObjects=[SpreadsheetRow1, SpreadsheetRow2, SpreadsheetRow3]
dict_var1_to_account2={1234:888, 1991:646, 90802:5443}
I've tried this:
for k, v in dict_var1_to_account2.iteritems():
if k in listOfSpreadsheetRowObjects:
if self.account1=k:
self.account2=v
But, it's not working, and I suspect it's my first "if" statement, because listOfSpreadsheetRowObjects is just a list of those objects. How would I access account1 of each object, so I can match them as needed?
Eventually, I should have three objects with the following information:
SpreadsheetRow
self.Account1=Account1
self.Account2=(v from my dictionary, if account1 matches the key in my dictionary)
You can use a generator expression within any() to check if any account1 attribute of those objects is equal with k:
if any(k == item.account1 for item in listOfSpreadsheetRows):
You can try to use the next function like this:
next(i for i in listOfSpreadsheetRows if k == i.account1)
If you have a dictionary d and want to get the value associated to the key x then you look up that value like this:
v = d[x]
So if your dictionary is called dict_of_account1_to_account2 and the key is self.Account1 and you want to set that value to self.Account2 then you would do:
self.Account2 = dict_of_account1_to_account2[self.Account1]
The whole point of using a dictionary is that you don't have to iterate through the entire thing to look things up.
Otherwise if you are doing this initialization of .Account2 after creating all the SpreadsheetRow objects then using self doesn't make sense, you would need to iterate through each SpreadsheetRow item and do the assignment for each one, something like this:
for row in listofSpreadsheetRowObjects:
for k, v in dict_of_account1_to_account2.iteritems():
if row.Account1 == k:
row.Account2 = v
But again, you don't have to iterate over the dictionary to make the assignment, just look up row.Account1 from the dict:
for row in listofSpreadsheetRowObjects:
row.Account2 = dict_of_account1_to_account2[row.Account1]

Create a dictionary using comprehension with nested for loops

I have a nested for loop in which I am setting the key, value for my new dictionary. Having found out about list comprehensions, I'm wondering if it's possible to use the same logic for a dictionary.
My attempt at one line comprehension for the dictionary which currently fails:
dict_contract_name_id = {each_contract: each_contract.id for each_inuring_layer in context.program_obj.inuringLayers for each_contract in each_inuring_layer.contracts}
It fails by saying TypeError: unhashable type: 'ContractWithId'.
Actual code I'm trying to convert to one line comprehension:
dict_contract_name_id = {}
for each_inuring_layer in context.program_obj.inuringLayers:
for each_contract in each_inuring_layer.contracts:
if each_contract.name in contracts:
dict_contract_name_id[each_contract.name] = each_contract.id
You forgot the .name attribute, as well as the if filter:
dict_contract_name_id = {
each_contract.name: each_contract.id
for each_inuring_layer in context.program_obj.inuringLayers
for each_contract in each_inuring_layer.contracts
if each_contract.name in contracts}
You tried to use the each_contract object as a key, and not just the name.

Categories