问题
I have a certain string k
that may or many not a key of a dict reversedmapping
, and another dict spendDict
where it may also be a key.
Why does the following check succeed (i.e. run to completion), for a value of k that is not a key of reversedmapping
:
if (k not in reversedmapping) or (reversedmapping[k] not in spendDict)
whereas I get a KeyError
(for k) when I change it to logical AND:
if (k not in reversedmapping) and (reversedmapping[k] not in spendDict)
:
And how do I rewrite the AND variant to avoid the KeyError?
回答1:
If (k not in reversedmapping)
is True
, then
(k not in reversedmapping) or (reversedmapping[k] not in spendDict)
short-circuits, which means it returns True
without evaluating
(reversedmapping[k] not in spendDict)
Since True or anything
is True
.
In contrast,
(k not in reversedmapping) and (reversedmapping[k] not in spendDict)
must evaluate both parts before Python can determine that the total expression
is True
.
If (k not in reversedmapping)
is True
, then reversedmapping[k]
will raise
KeyError
.
If (k not in reversedmapping)
is False
, then the expression short-circuits
and returns False
since False and anything
is False
.
So
(k not in reversedmapping) and (reversedmapping[k] not in spendDict)
will always either return False
or raise a KeyError
. There is no situation
under which it could return True
. Both conditions can not be True.
回答2:
Python's and
and or
are short-circuit operators. That means they only evaluate both parts of the expression when the answer isn't clear from the left hand operand. For and
, if the first operand evaluates to False
, then there's no way the result can be true, so the second operand isn't evaluated. For or
, it's the opposite - if the first operand evaluates to True
, the result is True
no matter what the second operand is.
In your case, if k
isn't in reversedmapping
, or
sees a true value on its left hand side and returns without evaluating the right hand sids, so no KeyError
. If you use an and
and the first test is true (k
is not in reversedmapping
), it's still forced to evaluate the second operand to see if they're both true, so it tries to pull k
from the dict and throws an exception.
来源:https://stackoverflow.com/questions/31331029/why-does-a-keyerror-get-thrown-in-logical-and-but-not-in-a-logical-or