I have a script where I read a file line by line and save some information to lists and dictionary. Namely, I store the keys (say ley1 and key2) to pass to the dictionary and a list to be stored as item in the dictionary.
It happens that I have to update a dictionary only if some conditions are met, i.e.:
myDict = {}
if mylist:
myDict[key1][key2] = mylist
Of course this will raise a KeyError if key2 does not exist already. Therefore, I introduced the following function:
def updateDict2keys(myDict,mykey1,mykey2,myitems):
"""
updates a dictionary by appending values at given keys (generating key2 if not given)
input: key1, key2 and items to append
output: dictionary orgnanized as {mykey1:{mykey2:myitems}}
"""
try:
myDict[mykey1][mykey2] = myitems
except KeyError:
myDict[mykey1] = {mykey2:myitems}
# output
return myDict
My question is: is it "safe" to call such a function in the main code inside a for loop like this?
with open(os.path.join(path+myfile)) as ntwkf:
# read file
rdlistcsv = csv.reader(ntwkf)
rowslist = [line for line in rdlistcsv]
ntwkJuncDict = {}
for idx,f in enumerate(rowslist): # loop over file lines
if f:
lineelmnt = f[0].split()[0]
else:
continue
# flags
isBranchName = True if lineelmnt=='definitions' else False
isJunction = True if lineelmnt=='connections' else False
# update dictionary
if isBranchName:
reachname = f[0].split()[2].replace("'","")
if isJunction:
usreach = f[0].split()[2].replace("'","")
uschain = float(f[1].replace("'","").replace(" ",""))
if usreach:
uslist = [usreach, uschain]
todivide.append(uslist)
ntwkJuncDict = updateDict2keys(ntwkJuncDict, reachname, 'upstream', uslist)
I must say, my code works pretty well, I am just asking myself (and yourselves of course!) if I am doing everything the python way and if there are smarter solutions.
Instead of accessing the primary key, use dict.setdefault
with a default empty dict
on it.
def updateDict2keys(myDict,mykey1,mykey2,myitems):
myDict.setdefault(mykey1, {})[mykey2] = myitems
return myDict
Note that your initial approach is also safe. Only lookup, not assignment, throws KeyError
. In the statement myDict[mykey1][mykey2] = myitems
, a KeyError
can only be thrown of mykey1
is not set. Thus, setting it to an empty dict
on a KeyError
does not overwrite anything.