Reputation: 6657
I have the following dictionary:
dic = {"a": "first", "b": "second"}
and it's ok, when I do the following:
print dic.get("a")
print dic.get("a", "asd")
print dic.get("a", dic.get("c"))
but when I use this method like this:
print dic.get("a", dic.get("c").split(" ",1)[0])
I receive the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'split'
I dont't understand the last case. The second argument calculated (dic.get("c") should be None - it's ok), but there is a key "a" in dictionary and first argument shouldn't fire calculating of the second argument.
How I can fix this? And why it happened?
TIA!
Upvotes: 1
Views: 245
Reputation: 184250
As others have explained, Python (like most other languages outside the functional family) evaluates all arguments of a function before calling it. Thus, dic.get("c")
is None
when key "c" doesn't exist in the dictionary and None
has no .split()
method, and this evaluation happens regardless of whether (and in fact before) the get
succeeds or fails.
Instead, use a short-circuiting Boolean operator or a conditional expression.
# if dic.get["a"] is always truthy when it exists
dic.get("a") or dic.get("c", "").split(" ", 1)[0]
# if dic["a"] could be non-truthy, e.g. empty string
dic["a"] if "a" in dic else dic.get("c", "").split(" ", 1)[0]
Upvotes: 2
Reputation: 36041
Maybe you just have typo and meant
print dic.get("a", dic.get("c")).split(" ",1)[0]
That is you meant to split the result of the outer dic.get
not the inner one.
Upvotes: 3
Reputation: 54262
dic.get("c")
Your dictionary doesn't contain "c", so it returns None
.
dic.get("c").split(" ",1)[0]
Since we know that dic.get("c")
is None
:
None.split(" ",1)[0]
None
has no split
method, so that's why you get that error.
The arguments are all evaluated before they're passed to the method.
Upvotes: 2
Reputation: 838686
The second argument is always evaluated whether or not it is used.
To fix it you can catch the exception that is raised when an item is not found instead of using get
.
try:
result = dic['a']
except KeyError:
result = dic['c'].split(' ', 1)[0]
print result
Upvotes: 3