# What is Python's equivalent of && (logical-and) in an if-statement?

## Question:

This doesn’t work:

``````if cond1 && cond2:
``````

Use `and` instead of `&&`.

Python uses `and` and `or` conditionals.

i.e.

``````if foo == 'abc' and bar == 'bac' or zoo == '123':
# do something
``````

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

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:]
``````

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:]
``````

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!

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

``````

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.

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         |
+------------------------------+---------------------+
``````

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`).

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 `print`s 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.

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

Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.