Python Forum
Simplifying multiple "or" conditions in if statement.
Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Simplifying multiple "or" conditions in if statement.
#8
The last call is every time true, because it's a generator expression.

g = (name in s for name in ('Bob', 'Ed'))
print(g) # Nothing is evaluated, it evaluates lazy
print(next(g))
print(next(g))
print(next(g)) # this will raise a StopIteration
Python supports following shortcuts:
  1. List comprehension, which makes a new list
    [char for char in 'An Object which is iterable']
  2. Dict comprehension, which makes a new dict. The order is not preserved.
    [n: char for n, char in enumerare('An Object which is iterable')]
    # using here enumerate just for demonstration. If you want to count Elements in an iterable, just use collections.Counter
    # collections.Counter('An Object which is iterable')
  3. Set comprehension which makes a new set. A set is a collection of elements, which are Unique. The order is not preserved.
    {char for char in 'An Object which is iterable'}
    # for example, you'll see the whitespace only one time
  4. Generator expression, which makes a generator. A generator is only executed when iterating over it. The state between iterations is saved in the generator.
    g = (char for char in 'An Object which is iterable')
    for c in g:
        print(g)
    # or written as a function
    def gen():
        for c in 'An Object which is iterable':
            yield c # yield keyword makes a generator
    
    for c in gen():
        print(c)

Now we come to the point that, all() and any(), takes iterables and valuates to bool(element)

all([True, True, True]) == True
all([True, False, True]) == False # all elements have to be checked
any([False, False, True]) == True # iterates till end has been reached
any([False, True, False]) == True # stops after second iteration


You can also pass a generator expression functions, if they are the only argument. In this case you don't have to use the parenthesis twice.
any((e for e in [False])) # this is valid
any(e for e in [False]) # this is valid
If you have a function, which takes more than one argument, you have to use parenthesis for a generator expression:

def foo(iterable, start):
    for index, element in enumerate(iterable, start):
        print(index, element)


foo((word for word in ['Hello' ,'World']), 1) # this is valid

foo((word for word in ['Hello' ,'World']), 1)
# SyntaxError: Generator expression must be parenthesized if not sole argument
Install ipython for Python3, which gives you better tabulator completion.
Then play around inside the repl.
In [1]: s = 'BobTom'

In [2]: any(name in s for name in ('Bob', 'Ed'))
Out[2]: True

In [3]: all(name in s for name in ('Bob', 'Ed'))
Out[3]: False

In [4]: (name in s for name in ('Bob', 'Ed'))
Out[4]: <generator object <genexpr> at 0x7f916f882c50>

In [5]: bool(name in s for name in ('Bob', 'Ed'))
Out[5]: True

In [6]: bool([])
Out[6]: False

In [8]: bool(tuple())
Out[8]: False

In [9]: bool('')
Out[9]: False

In [10]: bool('Foo')
Out[10]: True

In [11]: bool('False')
Out[11]: True

In [12]: bool('0')
Out[12]: True

In [13]: [name in s for name in ('Bob', 'Ed')]
Out[13]: [True, False]

In [14]: {name in s for name in ('Bob', 'Ed')}
Out[14]: {False, True}

In [15]: {name: name in s for name in ('Bob', 'Ed')}
Out[15]: {'Bob': True, 'Ed': False}

In [16]: (name in s for name in ('Bob', 'Ed'))
I hope this explains the use of list/dict/set comprehensions and generator expressions a little bit.
When you're using the if statement, it evaluates the bool. The object itself decides what it should return when __bool__() is called.

When calling bool(the_object)
  • empty string returns False
  • empty list returns False
  • empty tuple returns False
  • None returns False
  • 0 returns False
  • -1 returns True
  • 1 returns True
  • empty dict returns False
  • empty set returns False
  • normally all container types should return false, if they are empty
  • a function returns True
    def foo():
        pass
    bool(foo)
  • a generator returns True
    def gen():
        yield 1
    bool(gen)
  • a class returns True
    class Foo:
        pass
    bool(Foo)

You want to avoid the use of the three last examples. I am not sure about any use case to check the truthiness of a function, generator, class...
But you can do it accidentally, which gives you some output without an error, which leads to wrong conclusions.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Messages In This Thread
RE: Simplifying multiple "or" conditions in if statement. - by DeaD_EyE - Jul-22-2017, 09:09 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  How do you format Update statement with multiple conditions hammer 4 2,110 Dec-16-2021, 10:49 PM
Last Post: hammer
  multiple condition if statement problem FelixReiter 3 2,614 Jan-11-2021, 08:07 AM
Last Post: FelixReiter
  Multiple conditions when indexing an array with or without np.where noob2305 1 2,683 Oct-25-2020, 02:06 PM
Last Post: jefsummers
  Multiple conditions, one is null moralear27 1 2,204 Sep-13-2020, 06:11 AM
Last Post: scidam
  SyntaxError: multiple statements found while compiling a single statement Kayode_Odeyinka 1 2,996 Mar-12-2020, 05:50 PM
Last Post: micseydel
  multiple conditions Chandan 7 4,023 Jan-31-2020, 12:53 AM
Last Post: Chandan
  Help for simplifying code mmk1995 8 4,182 Sep-24-2019, 02:04 PM
Last Post: perfringo
  simplifying a stack of elifs Skaperen 8 4,114 Aug-17-2019, 04:13 AM
Last Post: Skaperen
  Simplifying my code ilondire05 5 3,793 Jul-21-2019, 03:21 AM
Last Post: scidam
  SyntaxError: multiple statements found while compiling a single statement DragonG 1 5,460 Nov-26-2018, 05:33 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020