Bottom Page

Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Simplifying multiple "or" conditions in if statement.
#1
The first if statement, with "in s" after each string works.  However,  the second if statement, combining the strings with parentheses does not.

It seems I shouldn't have to repeat "in s."  Is there a way?

s='Bob' 'Tom'

if 'Tom' in s or 'Bob' in s:

if ('Tom' or 'Bob') in s:
You like this post
Quote
#2
https://python-forum.io/Thread-Multiple-...or-keyword
:)
You like this post
Feel like you're not getting the answers you want? Checkout the help/rules for things like what to include/not include in a post, how to use code tags, how to ask smart questions, and more.

Pro-tip - there's an inverse correlation between the number of lines of code posted and my enthusiasm for helping with a question :)
Quote
#3
works for me
python 3.6.2
>>> s='Bob' 'Tom'
>>> s
'BobTom'
>>> ('Tom' or 'Bob')
'Tom'
>>> 'Tom' in s
True
>>> 'Bob' in s
True
>>> if ('Tom' or 'Bob') in s:
...     print('Yup')
...
Yup
>>>
You like this post
Quote
#4
Be a little careful of the way you test an expression such as this.
What could be happening is that it is just taking one of the values and using that.
You probably should test if 'Bob' or 'Carol', 'Alice' or 'Bob', 'Ted' or 'Alice' and even 'Carol' or 'Bob' (i.e. is it just taking the first name) also produce the required result.
(The principle behind this is to test edge cases, and for false positives and false negatives.)
Susan
You and micseydel like this post
Quote
#5
Quote:works for me

I'm sorry, I mistyped my example.  I meant to search on something not in the string; in the corrected example Ed.

The first works but the second doesn't.  However, I was confused as "if ('Bob' or 'Ed') in s:" works.  Regardless, the link provided as a response helps.

s='Bob' 'Tom'

if 'Ed' in s or 'Bob' in s:

if ('Ed' or 'Bob') in s:
You like this post
Quote
#6
if ('Ed' or 'Bob') in s:
This code checks always if 'Ed' in s:

The or operator is a binary operation, which is checking for trueness.
A str object with the length 0 is False. All other str objects are True.
With your code you'll always get 'Ed' after evaluating the expression.

What you want to do:

s = 'BobTom'

for name in ('Bob', 'Ed'):
    if name in s:
        print('Name {} is in {}'.format(name, s))
If you want to check if any of the names is in the string, you can write it more compact:

any(name in s for name in ('Bob', 'Ed'))
If you want to check if all the names are in the string, you can use the built-in function all:

all(name in s for name in ('Bob', 'Ed'))
You like this post
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Quote
#7
(Jul-21-2017, 01:32 PM)DeaD_EyE Wrote: If you want to check if any of the names is in the string, you can write it more compact:

any(name in s for name in ('Bob', 'Ed'))

Wonderful.  I knew I could use a loop but was looking for something more compact.  However, I don't see the need for "any."  The following seems to work:

(name in s for name in ('Bob', 'Ed'))
Is there an advantage to using "any" I'm not seeing.  I understand using "all" if that's required.
You like this post
Quote
#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.
You, snippsat, nilamo And 1 others like this post
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Quote
#9
(Jul-22-2017, 09:09 AM)DeaD_EyE Wrote: The last call is every time true, because it's a generator expression.
I hope this explains the use of list/dict/set comprehensions and generator expressions a little bit.

A good answer quite well explained.  I thank you kindly.
You like this post
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  multiple conditions Chandan 7 293 Jan-31-2020, 12:53 AM
Last Post: Chandan
  Help for simplifying code mmk1995 8 375 Sep-24-2019, 02:04 PM
Last Post: perfringo
  simplifying a stack of elifs Skaperen 8 601 Aug-17-2019, 04:13 AM
Last Post: Skaperen
  Simplifying my code ilondire05 5 373 Jul-21-2019, 03:21 AM
Last Post: scidam
  SyntaxError: multiple statements found while compiling a single statement DragonG 1 1,378 Nov-26-2018, 05:33 AM
Last Post: Larz60+
  My program subtracts fractions, but for some reason isn't simplifying them RedSkeleton007 9 1,780 Mar-03-2018, 11:45 AM
Last Post: Gribouillis
  Help with multiple conditions on ATM program jakegold98 6 4,545 Dec-06-2017, 05:18 PM
Last Post: jakegold98

Forum Jump:


Users browsing this thread: 1 Guest(s)