The most Pythonic way of checking if a value in a

2019-02-06 03:13发布

Say I have a dictionary, and I want to check if a key is mapped to a nonempty value. One way of doing this would be the len function:

mydict = {"key" : "value", "emptykey" : ""}
print "True" if len(mydict["key"]) > 0 else "False"  # prints true
print "True" if len(mydict["emptykey"]) > 0 else "False"  # prints false

However, one can rely on the semantics of Python and how if an object is defined it evaluates to true and leave out the len call:

mydict = {"key" : "value", "emptykey" : ""}
print "True" if mydict["key"] else "False"  # prints true
print "True" if mydict["emptykey"] else "False"  # prints false

However, I'm not sure which is more Pythonic. The first feels "explicit is better than implicit", however the second feels "simple is better than complex".

I also wonder if the leaving out the len call could bite me as the dict I'm working with doesn't necessarily contain strings, but could contain other len-able types (lists, sets, etc). OTOH, in the former (with the len call) if None gets stored as a value the code will blow up, whereas the non-len version will work as expected (will eval to false).

Which version is safer and more Pythonic?

Edit: clarifying assumptions: I know the key is in the dictionary, and I know values will be len-able. I also cannot avoid having zero-length values enter the dictionary.

Edit #2: It seems like people are missing the point of my question. I'm not trying to determine the most Pythonic/safest way of checking if a key is present in a dictionary, I'm trying to check if a value has zero length or not

8条回答
\"骚年 ilove
2楼-- · 2019-02-06 03:23

The title and the first sentence actually express two slightly different questions.

For the title question

The most Pythonic way of checking if a value in a dictionary is defined

I'd go with

"key" in mydict

and for the second question

Say I have a dictionary, and I want to check if a key is mapped to a nonempty value.

I'd go with

"key" in mydict and bool(mydict["key"])

The first part of which checks to see whether "key" is present in mydict and the second part returns true for all values of "key" other then False, None, the empty string, the empty dictionary, the empty list and 0.

查看更多
等我变得足够好
3楼-- · 2019-02-06 03:23

Of your two examples I prefer the second.

However, I advise against storing the empty keys. Also a defaultdict would work well here:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d[1].append(1)
>>> 1 in d
True

If you must store empty keys you don't need the string values "True" and "False". Just do this:

print bool(mydict[key])
查看更多
forever°为你锁心
4楼-- · 2019-02-06 03:27

Your initial conditions are not Pythonic. Why are you storing a key with an empty value? Can you delete the key instead of setting it to None?

The Pythonic way is to check key existence with if key in dictionary, not checking for a non-empty value.

查看更多
孤傲高冷的网名
5楼-- · 2019-02-06 03:32

If you know the key is in the dictionary, use

if mydict["key"]:
    ...

It is simple, easy to read, and says, "if the value tied to 'key' evaluates to True, do something". The important tidbit to know is that container types (dict, list, tuple, str, etc) only evaluate to True if their len is greater than 0.

It will also raise a KeyError if your premise that a key is in mydict is violated.

All this makes it Pythonic.

查看更多
6楼-- · 2019-02-06 03:41

From here:

In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true.

I think it's safe to say that directly evaluating it is your best option - although, as @phihag said, it's safer to use get instead, as it will protect you from a KeyError.

查看更多
欢心
7楼-- · 2019-02-06 03:42
print (bool(mydict.get('key')))

or, in an if statement:

print ('True' if mydict.get('key') else 'False')

If you the value not being present is an error case (i.e. you expect it to be there), you should choose solution #2, i.e.

print ('True' if mydict['key'] else 'False')

That allows mydict['key'] to choose the most efficient definition for being empty. For some objects (such as ones in clusters), determining the actual length is a fairly complicated operation, whereas it's simple to determine whether the object is empty or not.

You could also compare to '', i.e. mydict['key'] == '', to make your expression abundantly clear. Using len works, but is not as intuitive.

In summary, leave it to the tested object to define whether it's empty or not and just cast it to bool.

查看更多
登录 后发表回答