The problem is not with the operator in
, but on the logical operator or
and and
that you used. Do:
>>> (2 or 10) in range(1,6)
Do not check if the numbers 2 and 10 are in the range(1, 6)
. What happens is that Python will first parse the logical expression 2 or 10
and check that the output of this expression belongs to range(1, 6)
. Python interprets any non-zero integer value as true and only zero as false. So do 2 or 10
, for Python, it is the same as True or True
. In this case, as the logical operator is the or
and the first operand is true, no matter the value of the second, then the value of the first, 2 is returned. So Python will check only if 2 is in range(1, 6)
, returning true. This behavior of returning a value before analyzing the entire logic expression is called short-circuit.
Logic operations in Python 2.7 (More about how Python evaluates logical expression)
So in the other case, (10 or 2) in range(1,6)
, the same logic occurs. The number 10 will be analyzed as true and the operator or
, occurs again the short-circuit of the logical expression, returning as a result the appropriate value 10. Thus, Python will verify if 10 in range(1, 6)
, returning false.
In the third expression:
>>> (10 and 2) in [1,2,3,4,5,6,7,8,9]
The only thing that changes is the logical operator, of or
for and
. Being and
, the logic expression will not short-circuit when the first operand is true, then the second operand, 2, will be analyzed and returned. Thus, the return of 10 and 2
will be 2 and Python will check if it is in [1,2,3,4,5,6,7,8,9]
, returning true.
Just take the test:
# (2 or 10) ocorre o curto-circuito, retornando o primeiro operando: 2
print(2 or 10)
# (10 or 2) ocorre o curto-circuito, retornando o primeiro operando: 10
print(10 or 2)
# (2 and 10) não ocorre o curto-circuito, retornando o segundo operando: 10
print(2 and 10)
# (10 and 2) não ocorre o curto-circuito, retornando o segundo operando: 2
print(10 and 2)
See working on Ideone.
The short circuit occurs when:
- On the operator
or
, the first operand is true, for True or X
will always be true independent of X
;
- On the operator
and
, the first operand is false, for False and X
will always be false regardless of X
;
If on the operator or
the first operand is false, the value of the second operand is returned. If the operator and
the first operand is true, the value of the second operand is returned.
To check if a list of numbers is contained in another list with Python, you will need to do:
>>> all(x in range(1, 6) for x in [2, 10])
In this case, all elements of [2, 10]
shall be covered by x
and checked, one by one, if they belong to the set range(1, 6)
. If at least one does not belong, the function all
return false. Return true if all elements belong to the other set.
That is, the code below results in False
, for 10 does not belong to range(1, 6)
:
>>> all(x in range(1, 6) for x in [2, 10])
But the code below returns True
, because all the elements belong to range(1, 6)
:
>>> all(x in range(1, 6) for x in [2, 4])
See working on Ideone.
Another way is to work with mathematical sets. To know if the set B
is a subset of the set A
, in Python, just do:
>>> B.issubset(A)
This way, to know if [2, 10]
is a subset of range(1, 6)
, do:
>>> A = set(range(1, 6))
>>> B = set([2, 10])
>>> B.issubset(A)
False
Returns false, because 10 does not belong to the set A
. However, if you test with the set [2, 3]
:
>>> A = set(range(1, 6))
>>> B = set([2, 3])
>>> B.issubset(A)
True
For the whole {2, 3}
is a subset of range(1, 6))
.
See working on Ideone.
I thought very good his explanation, I was here breaking my head to know why [1,2,3] in [1,2,3] returned False. Still, I didn’t find it very user friendly for beginners. But I guess I get used to it. Thank you so much.
– Lean Marqs
Actually it is, but you’re probably still misinterpreting at first glance. This will change over time and you will see that such a notation makes sense, as doing
[1,2,3] in [1,2,3]
checks if the first entire list belongs to the second. Verification is not done element by element.– Woss