Reputation: 57
I have some problem with the "any" syntax. I have two lists.
mainseq = ["hali", "hulu", "habi"]
seq = ["a", "b", "c", "d"]
I want to find if elements in seq
exist in mainseq
.
for each in seq:
if any(each in halum for halum in mainseq):
print each
This gives me "a" and "b" as expected. But when I remove the "any" syntax, I get all the values in seq
, even though "c" and "d" are not there in mainseq
.
for each in seq:
if (each in halum for halum in mainseq):
print each
What is happening behind the scenes with and without the "any" function?
Upvotes: 4
Views: 534
Reputation: 43245
any
returns a boolean value True
or False
.
Your statement (each in halum for halum in mainseq)
returns a generator which evaluates to truthy value, hence code always falls in the if
block.
Here is a more verbose code explaining this:
mainseq = ["hali", "hulu", "habi"]
seq = ["a", "b", "c", "d"]
print('Demo of any:\n')
for each in seq:
boolFlag = any(each in halum for halum in mainseq)
print('Any returned:{0}'.format(boolFlag))
if boolFlag:
print each
print('Demo of generator as truthy value:\n')
for each in seq:
boolFlag = (each in halum for halum in mainseq)
print('boolFlag is:{0}'.format(boolFlag))
if boolFlag:
print each
print('{0} is Truthy'.format(boolFlag))
Outputs:
Any returned:True
a
Any returned:True
b
Any returned:False
Any returned:False
Demo of generator as truthy value:
boolFlag is:<generator object <genexpr> at 0xb7272bbc>
a
<generator object <genexpr> at 0xb7272bbc> is Truthy
boolFlag is:<generator object <genexpr> at 0xb7272be4>
b
<generator object <genexpr> at 0xb7272be4> is Truthy
boolFlag is:<generator object <genexpr> at 0xb7272bbc>
c
<generator object <genexpr> at 0xb7272bbc> is Truthy
boolFlag is:<generator object <genexpr> at 0xb7272be4>
d
<generator object <genexpr> at 0xb7272be4> is Truthy
Upvotes: 2
Reputation: 152695
To understand what is happening you could debug it by printing an equivalent list comprehension and the boolean
representation and any
:
for each in seq:
print(each)
print([each in halum for halum in mainseq])
print(any(each in halum for halum in mainseq))
print(bool(each in halum for halum in mainseq))
# a
# [True, False, True] <- contains more than one True element
# True <- so any returns True
# True <- boolean expression of a generator is always True
# b
# [False, False, True] <- contains one True element
# True <- so any returns True
# True <- boolean expression of a generator is always True
# c
# [False, False, False] <- no element is True
# False <- so any returns False
# True <- boolean expression of a generator is always True
# d
# [False, False, False] <- no element is True
# False <- so any returns False
# True <- boolean expression of a generator is always True
But remember that a generator will always evaluate to True
because a generator has no explicit boolean representation and doesn't have a length (see Truth-value-testing in the official documentation).
any
on the other hand consumes the generator and returns True
only if any element is True
. This is the case for each == a
and each == b
. So the if
condition will not always be triggered.
Upvotes: 5
Reputation: 1133
any() returns True if any element of the iterable is true. If the iterable is empty, return False.
So if any(each in halum for halum in mainseq):
looks at elements inside.
iterations where each is "a" or "b" contains those elements and therefore if statement is true. For cases of "c" and "d", iterable is empty, producing false.
When you remove any(), you are no longer looking inside the iterable but simply asking whether iterable itself is not true.
if (each in halum for halum in mainseq):
will always be true since it always will produce a valid generator object.
Upvotes: 1
Reputation: 20346
(each in halum for halum in mainseq)
is a generator expression. A generator expression is a truthy value. Using just that in an if
statement will always be True
, so the suite will always be executed. any()
searches an iterable for any value that is truthy. Therefore, using it will execute the suite only if any of the results of that generator expression is True
.
Upvotes: 2
Reputation: 205
Any
returns true if the list given has at least 1 element in it. You can achieve what you want by doing this instead:
for each in seq:
for halum in mainseq:
if each in halum:
print each
Upvotes: 0