1063

This doesn't work:

if cond1 && cond2:
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 39
    It seems to me that the interpreter should, rather than print out a cryptic "SyntaxError: invalid syntax" - detect that the user has used `&&` and suggest to them that they might want to use the keyword `and` instead. Same goes for things like `++` and other common operators from other languages. – ArtOfWarfare Sep 26 '13 at 17:28
  • 3
    @physicsmichael "there should be one, and preferably only one, obvious way to do it." `import this` – Nick T Sep 14 '14 at 20:24
  • 2
    `and` and `or` can also be used to evaluate the truthiness of expressions involving more than just boolean values. For more information, please see [this post](https://stackoverflow.com/q/47007680/4909087). – cs95 Dec 29 '18 at 12:07

9 Answers9

1841

Use and instead of &&.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 2
    what should i do for this: if x=='n' and y =='a' or y=='b': Will it work !? @ChristopheD – diffracteD Apr 02 '15 at 15:35
  • 12
    @diffracteD: Use parentheses if you want to override standard operator precedence (which you can learn about here: http://www.ibiblio.org/g2swap/byteofpython/read/operator-precedence.html) – ChristopheD Apr 02 '15 at 21:51
  • 4
    I like that [David Titarenco](http://stackoverflow.com/users/243613/david-titarenco) gave a cut-n-paste [example](http://stackoverflow.com/a/2485473/1153645) – Alexx Roche May 27 '15 at 16:33
  • 10
    I arrived here after I typed both `&&` and `AND` and got an error (not expecting python to want the lowercase word `and`). – Xeoncross Nov 22 '16 at 17:28
  • 2
    I think you should use & See: https://stackoverflow.com/questions/36921951/truth-value-of-a-series-is-ambiguous-use-a-empty-a-bool-a-item-a-any-o – Reddspark Jul 27 '17 at 20:24
  • 1
    Concise and accurate answer! For further info you can see Python3 "Boolean Operations — and, or, not" - https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not – Lavande Sep 03 '18 at 04:20
280

Python uses and and or conditionals.

i.e.

if foo == 'abc' and bar == 'bac' or zoo == '123':
  # do something
detly
  • 29,332
  • 18
  • 93
  • 152
David Titarenco
  • 32,662
  • 13
  • 66
  • 111
  • 6
    Don't forget that python also has not (well, and !) – inspectorG4dget Mar 21 '10 at 02:54
  • 11
    Does your example evaluate to "(if this and this) or that" OR "if this and (this or that)"? – Jeff Feb 19 '14 at 18:04
  • 16
    @Jeff Your first way. `and` [has higher precedence](https://docs.python.org/2/reference/expressions.html#operator-precedence) than `or`. – Buge Aug 26 '14 at 19:05
  • 1
    @Buge it looks like "or" is higher up in the table that you linked – Matt Dec 04 '17 at 14:59
  • 7
    @Matt the table goes from lowest precedence to highest. It's easier to remember the precedence if you've studied boolean algebra; "or" is addition and "and" is multiplication. – Michael Stroud Dec 05 '17 at 19:02
  • 1
    @Matt The python documentation table is irritating in that lowest on the screen is highest precedence and highest on the screen is lowest precedence. But it does say that in the text. Logical `and` has higher precedence than logical `or` in essentially all programming languages. Here's [c++](http://en.cppreference.com/w/cpp/language/operator_precedence) which has a more logical table with higher precedence at the top. – Buge Dec 09 '17 at 09:14
  • `True or True and False` If true, `and` is higher than `or` – vakio Feb 19 '20 at 00:35
104

I'm getting an error in the IF conditional. What am I doing wrong?

There reason that you get a SyntaxError is that there is no && operator in Python. Likewise || and ! are not valid Python operators.

Some of the operators you may know from other languages have a different name in Python. The logical operators && and || are actually called and and or. Likewise the logical negation operator ! is called not.

So you could just write:

if len(a) % 2 == 0 and len(b) % 2 == 0:

or even:

if not (len(a) % 2 or len(b) % 2):

Some additional information (that might come in handy):

I summarized the operator "equivalents" in this table:

Operator (other languages) Operator (Python)
&& and
|| or
! not

See also Python documentation: 6.11. Boolean operations.

Besides the logical operators Python also has bitwise/binary operators:

Logical operator Bitwise operator
and &
or |

There is no bitwise negation in Python (just the bitwise inverse operator ~ - but that is not equivalent to not).

See also 6.6. Unary arithmetic and bitwise/binary operations and 6.7. Binary arithmetic operations.

The logical operators (like in many other languages) have the advantage that these are short-circuited. That means if the first operand already defines the result, then the second operator isn't evaluated at all.

To show this I use a function that simply takes a value, prints it and returns it again. This is handy to see what is actually evaluated because of the print statements:

>>> def print_and_return(value):
...     print(value)
...     return value

>>> res = print_and_return(False) and print_and_return(True)
False

As you can see only one print statement is executed, so Python really didn't even look at the right operand.

This is not the case for the binary operators. Those always evaluate both operands:

>>> res = print_and_return(False) & print_and_return(True);
False
True

But if the first operand isn't enough then, of course, the second operator is evaluated:

>>> res = print_and_return(True) and print_and_return(False);
True
False

To summarize this here is another table:

Expression Right side evaluated?
True and ... Yes
False and ... No
True or ... No
False or ... Yes

The True and False represent what bool(left-hand-side) returns, they don't have to be True or False, they just need to return True or False when bool is called on them (1).

So in Pseudo-Code(!) the and and or functions work like these:

def and(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return evaluate(expr2)
    else:
        return left

def or(expr1, expr2):
    left = evaluate(expr1)
    if bool(left):
        return left
    else:
        return evaluate(expr2)

Note that this is pseudo-code not Python code. In Python you cannot create functions called and or or because these are keywords. Also you should never use "evaluate" or if bool(...).

Customizing the behavior of your own classes

This implicit bool call can be used to customize how your classes behave with and, or and not.

To show how this can be customized I use this class which again prints something to track what is happening:

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        print('__bool__ called on {!r}'.format(self))
        return bool(self.value)

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

So let's see what happens with that class in combination with these operators:

>>> if Test(True) and Test(False):
...     pass
__bool__ called on Test(True)
__bool__ called on Test(False)

>>> if Test(False) or Test(False):
...     pass
__bool__ called on Test(False)
__bool__ called on Test(False)

>>> if not Test(True):
...     pass
__bool__ called on Test(True)

If you don't have a __bool__ method then Python also checks if the object has a __len__ method and if it returns a value greater than zero. That might be useful to know in case you create a sequence container.

See also 4.1. Truth Value Testing.

NumPy arrays and subclasses

Probably a bit beyond the scope of the original question but in case you're dealing with NumPy arrays or subclasses (like Pandas Series or DataFrames) then the implicit bool call will raise the dreaded ValueError:

>>> import numpy as np
>>> arr = np.array([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> import pandas as pd
>>> s = pd.Series([1,2,3])
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> s and s
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

In these cases you can use the logical and function from NumPy which performs an element-wise and (or or):

>>> np.logical_and(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([False, False,  True, False])
>>> np.logical_or(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([ True, False,  True,  True])

If you're dealing just with boolean arrays you could also use the binary operators with NumPy, these do perform element-wise (but also binary) comparisons:

>>> np.array([False,False,True,True]) & np.array([True, False, True, False])
array([False, False,  True, False])
>>> np.array([False,False,True,True]) | np.array([True, False, True, False])
array([ True, False,  True,  True])

(1)

That the bool call on the operands has to return True or False isn't completely correct. It's just the first operand that needs to return a boolean in it's __bool__ method:

class Test(object):
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        return self.value

    __nonzero__ = __bool__  # Python 2 compatibility

    def __repr__(self):
        return "{self.__class__.__name__}({self.value})".format(self=self)

>>> x = Test(10) and Test(10)
TypeError: __bool__ should return bool, returned int
>>> x1 = Test(True) and Test(10)
>>> x2 = Test(False) and Test(10)

That's because and actually returns the first operand if the first operand evaluates to False and if it evaluates to True then it returns the second operand:

>>> x1
Test(10)
>>> x2
Test(False)

Similarly for or but just the other way around:

>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)

However if you use them in an if statement the if will also implicitly call bool on the result. So these finer points may not be relevant for you.

cocomac
  • 518
  • 3
  • 9
  • 21
MSeifert
  • 145,886
  • 38
  • 333
  • 352
41

Two comments:

  • Use and and or for logical operations in Python.
  • Use 4 spaces to indent instead of 2. You will thank yourself later because your code will look pretty much the same as everyone else's code. See PEP 8 for more details.
istruble
  • 13,363
  • 2
  • 47
  • 52
13

I went with a purlely mathematical solution:

def front_back(a, b):
  return a[:(len(a)+1)//2]+b[:(len(b)+1)//2]+a[(len(a)+1)//2:]+b[(len(b)+1)//2:]
Big Red
  • 163
  • 1
  • 3
12

You use and and or to perform logical operations like in C, C++. Like literally and is && and or is ||.


Take a look at this fun example,

Say you want to build Logic Gates in Python:

def AND(a,b):
    return (a and b) #using and operator

def OR(a,b):
    return (a or b)  #using or operator

Now try calling them:

print AND(False, False)
print OR(True, False)

This will output:

False
True

Hope this helps!

MarianD
  • 13,096
  • 12
  • 42
  • 54
geekidharsh
  • 3,549
  • 1
  • 20
  • 24
8

Probably this is not best code for this task, but is working -

def front_back(a, b):

 if len(a) % 2 == 0 and len(b) % 2 == 0:
    print a[:(len(a)/2)] + b[:(len(b)/2)] + a[(len(a)/2):] + b[(len(b)/2):]

 elif len(a) % 2 == 1 and len(b) % 2 == 0:
    print a[:(len(a)/2)+1] + b[:(len(b)/2)] + a[(len(a)/2)+1:] + b[(len(b)/2):] 

 elif len(a) % 2 == 0 and len(b) % 2 == 1:
     print a[:(len(a)/2)] + b[:(len(b)/2)+1] + a[(len(a)/2):] + b[(len(b)/2)+1:] 

 else :
     print a[:(len(a)/2)+1] + b[:(len(b)/2)+1] + a[(len(a)/2)+1:] + b[(len(b)/2)+1:]
bstpierre
  • 30,042
  • 15
  • 70
  • 103
-3

Use of "and" in conditional. I often use this when importing in Jupyter Notebook:

def find_local_py_scripts():
    import os # does not cost if already imported
    for entry in os.scandir('.'):
        # find files ending with .py
        if entry.is_file() and entry.name.endswith(".py") :
            print("- ", entry.name)
find_local_py_scripts()

-  googlenet_custom_layers.py
-  GoogLeNet_Inception_v1.py
Uki D. Lucas
  • 516
  • 6
  • 4
  • 15
    This question was asked and answered almost 7 years ago. What does your answer add to those answers that are already here? In general, unless you have something startlingly new to say, you should not add a new answer to an old question — where old is measured as multiple years — when there are good answers already available. – Jonathan Leffler Feb 04 '17 at 00:52
-4

A single & (not double &&) is enough or as the top answer suggests you can use 'and'. I also found this in pandas

cities['Is wide and has saint name'] = (cities['Population'] > 1000000) 
& cities['City name'].apply(lambda name: name.startswith('San'))

if we replace the "&" with "and", it won't work.

AlessioX
  • 3,167
  • 6
  • 24
  • 40
  • 2
    Single & won't short-circuit the expression (meaning both they will be evaluated regardless of the return value of the first expression) – user528025 May 27 '18 at 12:39