简体   繁体   中英

Issue with python “any” syntax

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" is 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? Please help.

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.

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:

http://ideone.com/AQ7dRs

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

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

(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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM