Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this expression always true when removing "any"?

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?

like image 322
Divine Light Avatar asked Apr 12 '16 11:04

Divine Light


2 Answers

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.

like image 66
MSeifert Avatar answered Sep 25 '22 16:09

MSeifert


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

like image 31
zondo Avatar answered Sep 26 '22 16:09

zondo