So I have a pair of dictionaries in python: (both have exactly the same keys)
defaults = {'ToAlpha': 4, 'ToRed': 4, 'ToGreen': 4, 'ToBlue': 4,}
bridged = {'ToAlpha': 3, 'ToRed': 0, 'ToGreen': 1, 'ToBlue': 2,}
When I iterate through one of the dictionaries I do a quick check to see if the other dict has the same key, if it does then print it.
for key, value in defaults.iteritems():
if bridged.get(key):
print key
What I would expect to see is:
ToAlpha
ToRed
ToGreen
ToBlue
But for some reason, 'ToRed' is not printed. I must be missing something really simple here, but have no idea might might be causing this.
bridged.get('ToRed')
and
defaults.get('ToRed')
both work independently, but when iterated through the loop... Nothing!
Any idea's?
0 is false. Use in to check for containment.
if key in bridged:
The problem is in the if statement when 'ToRed' gets passed.
if 0
returns false, so the key is not returned. Use
if key in bridged
The problem is when key is ToRed, then bridged.get('ToRed') will be 0.
So following will evaluate to False:
if bridged.get(key):
thereby not printing 'ToRed'.
Instead of this, use the in operator.
Using in the most pythonic way to check if a key is in a dictionary.
So check using this:
if key in bridged:
Final code now becomes:
>>> for key, value in defaults.iteritems():
if key in bridged:
print key
ToAlpha
ToRed
ToBlue
ToGreen
Related
I often deal with heterogeneous datasets and I acquire them as dictionaries in my python routines. I usually face the problem that the key of the next entry I am going to add to the dictionary already exists.
I was wondering if there exists a more "pythonic" way to do the following task: check whether the key exists and create/update the corresponding pair key-item of my dictionary
myDict = dict()
for line in myDatasetFile:
if int(line[-1]) in myDict.keys():
myDict[int(line[-1])].append([line[2],float(line[3])])
else:
myDict[int(line[-1])] = [[line[2],float(line[3])]]
Use a defaultdict.
from collections import defaultdict
d = defaultdict(list)
# Every time you try to access the value of a key that isn't in the dict yet,
# d will call list with no arguments (producing an empty list),
# store the result as the new value, and give you that.
for line in myDatasetFile:
d[int(line[-1])].append([line[2],float(line[3])])
Also, never use thing in d.keys(). In Python 2, that will create a list of keys and iterate through it one item at a time to find the key instead of using a hash-based lookup. In Python 3, it's not quite as horrible, but it's still redundant and still slower than the right way, which is thing in d.
Its what that dict.setdefault is for.
setdefault(key[, default])
If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.
example :
>>> d={}
>>> d.setdefault('a',[]).append([1,2])
>>> d
{'a': [[1, 2]]}
Python follows the idea that it's easier to ask for forgiveness than permission.
so the true Pythonic way would be:
try:
myDict[int(line[-1])].append([line[2],float(line[3])])
except KeyError:
myDict[int(line[-1])] = [[line[2],float(line[3])]]
for reference:
https://docs.python.org/2/glossary.html#term-eafp
https://stackoverflow.com/questions/6092992/why-is-it-easier-to-ask-forgiveness-than-permission-in-python-but-not-in-java
Try to catch the Exception when you get a KeyError
myDict = dict()
for line in myDatasetFile:
try:
myDict[int(line[-1])].append([line[2],float(line[3])])
except KeyError:
myDict[int(line[-1])] = [[line[2],float(line[3])]]
Or use:
myDict = dict()
for line in myDatasetFile:
myDict.setdefault(int(line[-1]),[]).append([line[2],float(line[3])])
I have the following function:
def calculate(blob, count_per_data):
return geometric_mean( [score_per_count[ count_per_data[data] ] for data in combinations(blob)] )
The problem with my code is that if data is not found in count_per_data I get an exception. Instead, I wish count_per_data["unknown"] to evaluate to 0, i.e. "unknown"'s count is 0.
In turn, the value 0 exists in score_per_count and is not equal to 0. In other words, the score associated with a count of 0 is not itself 0.
How would you recommend I fix the above code to achieve my goal?
If you want to make sure that, the data exists in count_per_data and the value of count_per_data exists in score_per_count, you can use the list comprehension as a filter, like this
return geometric_mean([score_per_count[count_per_data[data]] for data in combinations(blob) if data in count_per_data and count_per_data[data] in score_per_count])
More readable version,
return geometric_mean([score_per_count[count_per_data[data]]
for data in combinations(blob)
if data in count_per_data and count_per_data[data] in score_per_count])
But, if you want to use default values when key is not found in a dictionary, then you can use dict.get. Quoting from dict.get docs,
get(key[, default])
Return the value for key if key is in the dictionary, else default. If
default is not given, it defaults to None, so that this method never
raises a KeyError.
You can use it, like this
count_per_data.get(data, 0)
If data is not found in count_per_data, 0 will be used instead.
Add conditions to the comprehension list:
return geometric_mean([score_per_count[count_per_data[data]] for data in combinations(blob) if data in count_per_data.keys() and count_per_data[data]] in geometric_mean.keys() else 0)
This code is not bad, but I want to know how good programmers will write the code
if count.get('a') is None:
count['a'] = 0
You can use dict.setdefault :
count.setdefault('a', 0)
help on dict.setdefault:
>>> print dict.setdefault.__doc__
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
setdefault is the best answer, but for the record, the Pythonic way to check for a key in a dict is using the in keyword:
if 'a' not in count:
count['a'] = 0
Looking at the selection of answer, I believe the question is somewhat incorrectly phrased.
set a value in a dictionary if it is None?
In fact if the title is correct in asking about setting a value if it is None, setdefault doesn't set the value, instead returns that None.
a_dict = {'key': None}
assert a_dict.setdefault('key', True) is None
I don't think it's a very common situation when you want to update the dictionary if a key has a value of None (as opposed to not having that key at all, in which case the setdefault is the way to go.) or if it's not in there at all. In that case the following should work and seems the most pythonic to me.
if not a_dict.get('key'):
a_dict['key'] = 'value'
I'm having a problem with setdefault and unions not working like I expect them to. My code looks like:
#!/usr/bin/python3.3
kanjidic = {
'恕': {'radical':{'multi_radical': {'口心女'}}},
'靛': {'radical':{'multi_radical': {'亠宀月疋二青土'}}},
}
k_rad = {}
for k,v in kanjidic.items():
if 'radical' in v and 'multi_radical' in v['radical']:
print (k, set(v['radical']['multi_radical']))
k_rad[k] = k_rad.setdefault(k, set()).update(
set(v['radical']['multi_radical']))
print('>>', k_rad[k])
The print output looks like:
恕 {'口心女'}
>> None
靛 {'亠宀月疋二青土'}
>> None
If I substitute the two lines below for setting k_rad:
k_rad[k] = k_rad.setdefault(k, set())
k_rad[k].update(set(v['radical']['multi_radical']))
My output looks like this:
靛 {'亠宀月疋二青土'}
>> {'亠宀月疋二青土'}
恕 {'口心女'}
>> {'口心女'}
If I understand setdefault, (which obviously I don't) the output should be the same,right?
What am I missing? Why am is dict.setupdate(key,set()).update(set(...)) returning None?
As pointed out below, the problem is that update returns None. I really didn't understand
how update and setdefault work together. Since setdefault sets the dict to the default if
we're creating a new dict element and returning the the hash and update updates the element
I didn't need the assignment. All I really needed was:
for k,v in kanjidic.items():
if 'radical' in v and 'multi_radical' in v['radical']:
k_rad.setdefault(k, set()).update(v['radical']['multi_radical'])
Thanks for the assistance!
dict.setdefault returns a set in your case. And set.update is an in-place operation, which means it changes the original set and returns None. So if you assign the result to a variable you just assign it a None.
None seems to work as a dictionary key, but I am wondering if that will just lead to trouble later. For example, this works:
>>> x={'a':1, 'b':2, None:3}
>>> x
{'a': 1, None: 3, 'b': 2}
>>> x[None]
3
The actual data I am working with is educational standards. Every standard is associated with a content area. Some standards are also associated with content subareas. I would like to make a nested dictionary of the form {contentArea:{contentSubArea:[standards]}}. Some of those contentSubArea keys would be None.
In particular, I am wondering if this will lead to confusion if I look for a key that does not exist at some point, or something unanticipated like that.
Any hashable value is a valid Python Dictionary Key. For this reason, None is a perfectly valid candidate. There's no confusion when looking for non-existent keys - the presence of None as a key would not affect the ability to check for whether another key was present. Ex:
>>> d = {1: 'a', 2: 'b', None: 'c'}
>>> 1 in d
True
>>> 5 in d
False
>>> None in d
True
There's no conflict, and you can test for it just like normal. It shouldn't cause you a problem. The standard 1-to-1 Key-Value association still exists, so you can't have multiple things in the None key, but using None as a key shouldn't pose a problem by itself.
You want trouble? here we go:
>>> json.loads(json.dumps({None:None}))
{u'null': None}
So yea, better stay away from json if you do use None as a key. You can patch this by custom (de/)serializer, but I would advise against use of None as a key in the first place.
None is not special in any particular way, it's just another python value. Its only distinction is that it happens to be the return value of a function that doesn't specify any other return value, and it also happens to be a common default value (the default arg of dict.get(), for instance).
You won't cause any run-time conflicts using such a key, but you should ask yourself if that's really a meaningful value to use for a key. It's often more helpful, from the point of view of reading code and understanding what it does, to use a designated instance for special values. Something like:
NoSubContent = SubContentArea(name=None)
{"contentArea":
{NoSubContent:[standards],
SubContentArea(name="Fruits"): ['apples', 'bananas']}}
jsonify does not support a dictionary with None key.
From Flask import jsonify
def json_():
d = {None: 'None'}
return jsonify(d)
This will throw an error:
TypeError: '<' not supported between instances of 'NoneType' and 'str'
It seems to me, the larger, later problem is this. If your process is creating pairs and some pairs have a "None" key, then it will overwrite all the previous None pairs. Your dictionary will silently throw out values because you had duplicate None keys. No?
Funny though, even this works :
d = {None: 'None'}
In [10]: None in d
Out[10]: True