Is "length and length" any different than just "length" in Python?
Question:
I’ve found the following code snippet:
length = length and length or len(string)
To me it appears that this should be equivalent to:
length = length or len(string)
Can I collapse the expression length and length
to just be length
or will I get a different result in some cases?
Answers:
length and length or len(string)
is exactly equivalent to length or len(string)
. I think that that whoever wrote this code expected it to avoid the len(string)
call when length
is falsy, but that is not the case. For example:
>>> None and None or len('foo')
3
Since and
had higher precedence than or
, we can rewrite the expression as follows:
(length and length) or len('foo')
length and length
will always evaluate to length
, so the two expressions are equivalent.
The line is nonsense. Let’s take a look at the options we have:
-
length
is falsy (so 0
, an empty list, an empty string, etc.). Python will return the value of length
because there is no point in looking at the rest of the expression as the and
operator evaluates to False
whatever the right-hand side evaluates to. It then tests length or len(string)
and returns len(string)
.
-
length
is not falsy. Python evaluates length and length
, resolves that to the value of length
, then tests length or len(string)
, and because length
is truthy, returns length
. After all, or
will now always resolve to True
and there is no point in looking at len(string)
.
This basically comes down to length = length or len(string)
, the length and length
is a no-op.
I’ve found the following code snippet:
length = length and length or len(string)
To me it appears that this should be equivalent to:
length = length or len(string)
Can I collapse the expression length and length
to just be length
or will I get a different result in some cases?
length and length or len(string)
is exactly equivalent to length or len(string)
. I think that that whoever wrote this code expected it to avoid the len(string)
call when length
is falsy, but that is not the case. For example:
>>> None and None or len('foo')
3
Since and
had higher precedence than or
, we can rewrite the expression as follows:
(length and length) or len('foo')
length and length
will always evaluate to length
, so the two expressions are equivalent.
The line is nonsense. Let’s take a look at the options we have:
-
length
is falsy (so0
, an empty list, an empty string, etc.). Python will return the value oflength
because there is no point in looking at the rest of the expression as theand
operator evaluates toFalse
whatever the right-hand side evaluates to. It then testslength or len(string)
and returnslen(string)
. -
length
is not falsy. Python evaluateslength and length
, resolves that to the value oflength
, then testslength or len(string)
, and becauselength
is truthy, returnslength
. After all,or
will now always resolve toTrue
and there is no point in looking atlen(string)
.
This basically comes down to length = length or len(string)
, the length and length
is a no-op.