Python Generators

Python Tutorial › Functions › Generators

Python Generators

IntermediateLesson 29 of 4710 min read8 runnable examples

A generator is a function that produces a sequence of values lazily, one at a time, using yield. Generators make iterators easy to write and let you process huge or endless data without loading it all into memory.

In this lesson
  • Write generator functions with yield
  • Understand how a generator pauses and resumes
  • Use generator expressions
  • Chain generators into pipelines

Your first generator

A function that contains yield is a generator function. Calling it does not run the body; it returns a generator object. Each next() runs the body until the next yield.

Python
def countdown(n):    while n > 0:        yield n        n -= 1 gen = countdown(3)print(gen)print(next(gen), next(gen), next(gen))print(list(countdown(5)))
Output
<generator object countdown at 0x000001D0A798A800>
3 2 1
[5, 4, 3, 2, 1]

Compare with the iterator class in the Iterators lesson: the same behaviour in four lines.

yield pauses, it does not end

return ends a function. yield hands out a value and pauses, keeping all local variables, until the next request.

Python
def steps():    print("start")    yield 1    print("after first yield")    yield 2    print("finished") for value in steps():    print("got", value)
Output
start
got 1
after first yield
got 2
finished

Why generators save memory

A list holds every item at once. A generator holds only its current state.

Python
import sys numbers_list = [n * n for n in range(1_000_000)]numbers_gen = (n * n for n in range(1_000_000)) print(sys.getsizeof(numbers_list) > 1_000_000)print(sys.getsizeof(numbers_gen) < 1_000)print(sum(numbers_gen))
Output
True
True
333332833333500000
Note

The exact byte sizes depend on the Python version, which is why the example prints comparisons. The list needs megabytes; the generator needs a few hundred bytes whatever the range.

Generator expressions

Round brackets around a comprehension make a generator expression. When it is the only argument to a function, you can drop the extra brackets:

Python
words = ["python", "generators", "save", "memory"]print(max(len(w) for w in words))print(any(w.startswith("g") for w in words))lengths = (len(w) for w in words)print(next(lengths), list(lengths))
Output
10
True
6 [10, 4, 6]

Infinite generators

Because values are produced on demand, a generator can run forever. Take only what you need:

Python
def fibonacci():    a, b = 0, 1    while True:        yield a        a, b = b, a + b fib = fibonacci()print([next(fib) for _ in range(10)])
Output
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Generator pipelines

Chain generators so each one processes the output of the previous one. Only one item flows through the pipeline at a time, which is how large log files are processed efficiently.

Python
log_lines = [    "INFO start",    "ERROR db timeout",    "INFO request ok",    "ERROR disk full",] def errors(lines):    for line in lines:        if line.startswith("ERROR"):            yield line def messages(lines):    for line in lines:        yield line.split(" ", 1)[1] for msg in messages(errors(log_lines)):    print(msg)
Output
db timeout
disk full

yield from

yield from hands out every item of another iterable, which is perfect for recursive generators:

Python
def flatten(items):    for item in items:        if isinstance(item, list):            yield from flatten(item)        else:            yield item print(list(flatten([1, [2, [3, 4]], 5])))
Output
[1, 2, 3, 4, 5]

Generators are single-use

Python
gen = (x for x in range(3))print(list(gen))print(list(gen))
Output
[0, 1, 2]
[]

Call the generator function again (or rebuild the expression) when you need the values a second time.

Check your understanding

Predict the output

def g():    for i in range(3):        yield i * 10    yield "done" it = g()print(next(it), next(it), list(it))

Quick quiz

1. What does calling a generator function return?

2. What happens to local variables at a yield?

3. Which creates a generator expression?

Exercise: read in chunks

Write a generator chunks(items, size) that yields lists of size items, with a shorter final chunk if needed.

Input
chunks(list(range(1, 11)), 4)
Expected output
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10]
Hint 1

Loop with range(0, len(items), size) and yield a slice.

Program Practice

20 Python Iterator & Generator Programs

Every program has a step-by-step explanation, colour-coded code and its real output.

Start practising →
Related sets:All practice sets

Python generators FAQ

What is the difference between yield and return?

return sends back one value and ends the function. yield sends back a value and pauses, so the function can continue and yield more values later.

When should I use a generator instead of a list?

When the data is large, endless, or only needed once in order, such as reading a big file line by line or streaming API results.

Can a generator be reused?

No. Once exhausted it stays empty. Call the generator function again to get a fresh one.

Python List Comprehension

List comprehension is a concise and expressive way of creating lists in Python. It allows you to define a list and its elements within a single line of code, combining the functionality of a for loop, optional if conditions, and even nested loops. List comprehensions are preferred for their readability and efficiency compared to traditional for loops.

  1. Simple For Loop List Comprehension:

This type of list comprehension is used to create a list by iterating over elements from an iterable (e.g., list, tuple, string) without any filtering or conditions. Here’s an example:

# Example list
numbers = [1, 2, 3, 4, 5]

# List comprehension without filtering or conditions
new_list = [num for num in numbers]

print(new_list) # Output: [1, 2, 3, 4, 5]
  1. Loop and If Condition List Comprehension:

This type of list comprehension includes an if condition to filter elements while iterating over the iterable. Only elements that satisfy the condition are included in the new list. Here’s an example:

# Example list
numbers = [1, 2, 3, 4, 5, 6]

# List comprehension with an if condition
even_numbers = [num for num in numbers if num % 2 == 0]

print(even_numbers) # Output: [2, 4, 6]
  1. Loop and If-Else Condition List Comprehension:
# Example list
numbers = [1, 2, 3, 4, 5, 6]

# List comprehension with if-else condition
result = ['Even' if num % 2 == 0 else 'Odd' for num in numbers]

print(result)
# Output: ['Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even']

This type of list comprehension allows you to perform different operations based on the if-else condition while iterating over the iterable. Here’s an example:

  1. Nested Loop List Comprehension:

This type of list comprehension allows you to use nested loops for creating more complex lists by iterating over multiple iterables simultaneously. Here’s an example:

# Example nested loops
colors = ['red', 'green', 'blue']
objects = ['ball', 'box', 'pen']

# List comprehension with nested loops
combinations = [f"{color} {obj}" for color in colors for obj in objects]

print(combinations)
# Output: ['red ball', 'red box', 'red pen', 'green ball', 'green box', 'green pen', 'blue ball', 'blue box', 'blue pen']

Shallow Copy and Deep Copy of Lists in Python:

In Python, when dealing with lists or other compound data structures, understanding the concepts of shallow copy and deep copy is crucial. Both concepts involve creating a new copy of an existing list, but they differ in how they handle nested objects within the list.

  1. Shallow Copy:

A shallow copy of a list creates a new list object but does not create copies of the elements inside the list. Instead, it copies references to the original objects. This means that changes made to nested objects within the copied list will affect the original list, and vice versa. To perform a shallow copy, you can use the `copy()` method or the slicing notation `[:]`. Example of Shallow Copy:

import copy

# Original list with a nested list
original_list = [[1, 2, 3], [4, 5, 6]]

# Shallow copy using the copy() method
shallow_copy1 = original_list.copy()

# Shallow copy using slicing notation
shallow_copy2 = original_list[:]

# Modifying a nested element in the copied list
shallow_copy1[0][0] = 99

print("Original List:", original_list)
# Output: Original List: [[99, 2, 3], [4, 5, 6]]

print("Shallow Copy 1:", shallow_copy1)
# Output: Shallow Copy 1: [[99, 2, 3], [4, 5, 6]]

print("Shallow Copy 2:", shallow_copy2)
# Output: Shallow Copy 2: [[99, 2, 3], [4, 5, 6]]
  1. Deep Copy:

A deep copy of a list creates a new list object and also recursively creates copies of all the nested objects within the original list. In other words, the copied list and its nested objects are entirely independent of the original list and its nested objects. To perform a deep copy, you need to use the `deepcopy()` function from the `copy` module. Example of Deep Copy:

import copy

# Original list with nested lists
original_list = [[1, 2, 3], [4, 5, 6]]

# Creating a deep copy
deep_copy = copy.deepcopy(original_list)

# Modifying a nested element in the deep copy
deep_copy[0][0] = 99

print("Original List:", original_list)
# Output: Original List: [[1, 2, 3], [4, 5, 6]]

print("Deep Copy:", deep_copy)
# Output: Deep Copy: [[99, 2, 3], [4, 5, 6]]

Shallow copy is faster and suitable when you want to create a new list but share references to nested objects. Deep copy is appropriate when you need an entirely independent copy of the original list and all its nested objects.

Python List Methods And Functions

Lists in Python have many built-in methods that you can use to modify or manipulate the list. Here are some of the most commonly used methods:

  1. append() – It is used to add an element to the end of the list.
# Define a list
my_list = ['apple', 'banana', 'cherry']

# Add an element to the end of the list
my_list.append('date')

# Print the updated list
print(my_list)
  1. extend() – It is used to add the elements of another list to the end of the list or to combine two lists.
# Define a list
my_list = ['apple', 'banana']

# Extend the list with a tuple
my_list.extend(('cherry', 'date'))

# Extend the list with a set

my_list.extend({'elderberry', 'fig'})

# Print the updated list
print(my_list)
  1. insert() – It is used to insert an element at a specific position in the list.
# Define a list
my_list = ['apple', 'banana', 'cherry']

# Insert an element at index 1
my_list.insert(1, 'date')

# Print the updated list
print(my_list)

         4. remove() – It is used to remove the first occurrence of an element from the list.

# Define a list
my_list = ['apple', 'banana', 'cherry', 'banana']

# Remove the first occurrence of 'banana'
my_list.remove('banana')

# Print the updated list
print(my_list)
  1. pop() – It removes and returns the element at a specific position in the list.
# Define a list
my_list = ['apple', 'banana', 'cherry']

# Remove and return the last element
removed_element = my_list.pop()

# Print the updated list and the removed element
print("Updated list:", my_list)
print("Removed element:", removed_element)

 6. sort() – It sorts the elements of the list in ascending order.

# Define a list of numbers
my_list = [3, 1, 4, 1, 5, 9, 2, 6]

# Sort the list in descending order
my_list.sort(reverse=True)

# Print the sorted list
print(my_list)

    7 .reverse() – It reverses the order of the elements in the list.

# Define a list of strings
my_list = ['apple', 'banana', 'cherry']

# Reverse the list
my_list.reverse()

# Print the reversed list
print(my_list)
  1. clear() – It is used to remove all elements from a list, effectively emptying the list. After the clear() function is applied to a list, the list becomes empty with a length of 0.
# Define a list of strings
my_list = ['apple', 'banana', 'cherry']

# Clear all elements from the list
my_list.clear()

# Print the cleared list
print(my_list)
  1. copy() – It creates a shallow copy of a list. The shallow copy means that a new list is created with the same elements as the original list, but the elements themselves are not duplicated. Any changes made to the elements in the copied list will also affect the original list, and vice versa.
# Define a list with immutable elements
my_list = [1, 2, 3]

# Create a shallow copy of the list
my_list_copy = my_list.copy()

# Modify the copied list
my_list_copy.append(4)

# Print both lists
print("Original list:", my_list)
print("Copied list:", my_list_copy)
  1. index() – It is used to find the index of the first occurrence of a specified element within a list. If the element is not found in the list, it raises a ValueError.
# Define a list
my_list = ['apple', 'banana', 'cherry']

# Find the index of 'banana'
index_of_banana = my_list.index('banana')

# Print the index
print("Index of 'banana':", index_of_banana)
  1. count() – It is used to count the number of occurrences of a specified element in a list.
# Define a list
my_list = ['apple', 'banana', 'cherry', 'banana', 'apple']

# Count occurrences of 'banana'
banana_count = my_list.count('banana')

# Print the count
print("Count of 'banana':", banana_count)

Updating list values:

Lists in Python are mutable, and their values can be updated by using the slice and assignment the ( = ) operator.

# Define a list
my_list = [1, 2, 3, 4, 5]

# Remove elements at indices 1 to 3
my_list[1:4] = []

# Print the updated list
print(my_list)

Built-in function for Python lists:

Here are some examples of commonly used built-in functions for lists in Python:

  1. len(): It returns the length of the list.
# Define a list
my_list = [1, 2, 3, 4, 5]

# Get the length of the list
list_length = len(my_list)

# Print the length
print("Length of the list:", list_length)
  1. max(): It returns the largest element in the list.
# Define a list of numbers
my_list = [1, 5, 3, 9, 2]

# Get the largest element in the list
largest_element = max(my_list)

# Print the largest element

print("Largest element:", largest_element)
  1. min(): It returns the smallest element in the list.
# Define a list of numbers
my_list = [10, 5, 20, 3, 8]

# Get the smallest element in the list
smallest_element = min(my_list)

# Print the smallest element
print("Smallest element:", smallest_element)
  1. sum(): It returns the sum of all elements in the list.
# Define a list of numbers
my_list = [1, 2, 3, 4, 5]

# Calculate the sum of the elements in the list
total_sum = sum(my_list)

# Print the total sum
print("Sum of the list:", total_sum)

       5. sorted(): It returns a new sorted list.

# Define a list of numbers
my_list = [5, 2, 9, 1, 5, 6]

# Get a new sorted list
sorted_list = sorted(my_list)

# Print the sorted list
print("Sorted list:", sorted_list)
  1. list(): It converts an iterable to a list.
# Define a tuple
my_tuple = (1, 2, 3, 4)

# Convert the tuple to a list
my_list = list(my_tuple)

# Print the list
print("List from tuple:", my_list)

       7. any(): It returns True if at least one element in the list is True.

# Define a list of Boolean values
my_list = [False, False, True, False]

# Check if any element is True
result = any(my_list)

# Print the result
print("Any True in the list:", result)
  1. all(): It returns True if all elements in the list are True.
# Define a list of Boolean values
my_list = [True, True, True]

# Check if all elements are True
result = all(my_list)

# Print the result
print("All True in the list:", result)

        9. enumerate(): It returns an iterator that contains tuples of (index, element) pairs.

# Define a list
my_list = ['apple', 'banana', 'cherry']

# Use enumerate to get index and element
for index, element in enumerate(my_list):
print(f"Index: {index}, Element: {element}")

# Output:

Index: 0, Element: apple
Index: 1, Element: banana
Index: 2, Element: cherry
  1. zip(): It returns an iterator that aggregates elements from multiple lists into tuples.
# Define two lists
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']

# Use zip to combine them into tuples
zipped = zip(list1, list2)

# Convert the zipped object to a list and print
zipped_list = list(zipped)
print(zipped_list)

        11.reversed(): It returns a reverse iterator that can be used to iterate over a list in reverse order.

# Define a list
my_list = [1, 2, 3, 4, 5]

# Convert the reversed iterator to a list
reversed_list = list(reversed(my_list))

# Print the reversed list
print(reversed_list)

Python List vs Tuple

Python Tutorial › Data Structures › List vs Tuple

Python List vs Tuple

BeginnerLesson 21 of 477 min read6 runnable examples

Lists and tuples both store ordered sequences, and both support indexing, slicing and loops. The difference that matters is that a list can change and a tuple cannot. That one difference decides which to use.

In this lesson
  • The key differences at a glance
  • Memory and speed compared
  • Why tuples can be dict keys
  • A simple rule for choosing

Differences at a glance

ListTuple
Syntax[1, 2, 3](1, 2, 3)
MutableYes: add, remove, change itemsNo
MethodsMany: append, remove, sort…Two: count, index
Can be a dict key / set itemNoYes, if its items are hashable
MemoryMoreLess
Typical useA collection that grows or changesA fixed record of values

Mutability in practice

Python
cart = ["pen", "book"]cart.append("bag")cart[0] = "pencil"print(cart) location = (18.52, 73.86)print(hasattr(location, "append"))
Output
['pencil', 'book', 'bag']
False

Memory and speed

A tuple uses less memory than a list with the same items, because a list keeps spare room so it can grow.

Python
import sys items_list = [1, 2, 3, 4, 5]items_tuple = (1, 2, 3, 4, 5)print(sys.getsizeof(items_list), sys.getsizeof(items_tuple))
Output
104 88

Creating a tuple of constants is also faster, because Python can build it once when the code is compiled:

Python
import timeit print(timeit.timeit("[1, 2, 3, 4, 5]", number=1_000_000) > timeit.timeit("(1, 2, 3, 4, 5)", number=1_000_000))
Output
True
Note

The exact sizes and timings depend on your Python version and computer. The direction does not: tuples are smaller and faster to create.

Hashability: tuples as keys

Only immutable objects can be dictionary keys or set members.

Python
visited = {(0, 0), (0, 1), (1, 1)}print((0, 1) in visited) grid = {(2, 3): "wall", (4, 1): "door"}print(grid[(4, 1)])
Output
True
door
Python
visited = {[0, 0], [0, 1]}
Output
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    visited = {[0, 0], [0, 1]}
              ^^^^^^^^^^^^^^^^
TypeError: cannot use 'list' as a set element (unhashable type: 'list')

Converting between them

Python
t = (3, 1, 2)lst = list(t)lst.sort()t = tuple(lst)print(t)
Output
(1, 2, 3)

Which should you use?

  • Use a list when the collection will change: items are added, removed or sorted, such as a shopping cart or a queue of test cases.
  • Use a tuple when the values belong together and should not change, such as (latitude, longitude), an RGB colour, a function returning several values, or a dictionary key.

Check your understanding

Quick quiz

1. Which can be used as a dictionary key?

2. Which uses less memory for the same five numbers?

3. You need to store an employee’s (id, name, joining date) record that never changes. Which fits best?

Program Practice

List vs tuple FAQ

Is a tuple faster than a list in Python?

Creating and iterating over a tuple is slightly faster and it uses less memory. The difference rarely matters; choose based on whether the data should change.

Why use a tuple instead of a list?

To signal that the data is fixed, to protect it from accidental changes, to use it as a dictionary key or set member, and to save a little memory.

Can a tuple contain a list?

Yes. The tuple cannot be changed, but the list inside it can. Such a tuple is not hashable, so it cannot be a dict key.

Python Lists

Python Tutorial › Data Structures › Lists

Python Lists

BeginnerLesson 18 of 4712 min read11 runnable examples

A list stores many values in one variable, in order. You will use lists in almost every Python program you write, from a shopping cart to a set of test results.

In this lesson
  • Create lists of any type
  • Read items with indexing and slicing
  • Add, change and remove items
  • Loop through a list
  • Sort a list two ways
  • Avoid the shared-list copy bug

What is a list in Python?

A list is written with square brackets, with items separated by commas. One list can hold numbers, strings, booleans, None and even other lists.

Python
fruits = ["apple", "banana", "cherry"]mixed = [1, "two", 3.0, True, None]empty = [] print(fruits)print(type(fruits))print(len(mixed), len(empty))
Output
['apple', 'banana', 'cherry']
<class 'list'>
5 0
Note

Lists are ordered (items keep their position), mutable (you can change them after creating them) and they allow duplicates.

You can also build a list from any iterable with list(), for example from a string or a range.

Python
print(list("abc"))print(list(range(1, 6)))
Output
['a', 'b', 'c']
[1, 2, 3, 4, 5]

Indexing and slicing

Every item has a position, called its index. Counting starts at 0 from the left and at -1 from the right.

Python
nums = [10, 20, 30, 40, 50] print(nums[0])      # first itemprint(nums[-1])     # last itemprint(nums[1:4])    # items at index 1, 2, 3print(nums[::-1])   # reversed copy
Output
10
50
[20, 30, 40]
[50, 40, 30, 20, 10]
Tip

A slice nums[start:stop] includes start but stops before stop. That is why nums[1:4] returns three items. Leave out start or stop to go from the beginning or to the end.

Reading an index that does not exist raises an IndexError. A slice never does: it just returns fewer items.

Python
nums = [10, 20, 30]print(nums[1:10])print(nums[5])
Output
[20, 30]
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(nums[5])
          ~~~~^^^
IndexError: list index out of range

Add, change and remove items

Python
cart = ["pen", "book"] cart.append("bag")        # add to the endcart.insert(1, "ink")     # add at index 1cart[0] = "pencil"        # replace an itemprint(cart) last = cart.pop()         # remove and return the last itemprint(last, cart) cart.remove("ink")        # remove by valueprint(cart)
Output
['pencil', 'ink', 'book', 'bag']
bag ['pencil', 'ink', 'book']
['pencil', 'book']

Python list methods you will use most

MethodWhat it doesReturns
append(x)Adds x to the endNone
insert(i, x)Adds x before index iNone
extend(items)Adds every item from another iterableNone
remove(x)Removes the first x; raises ValueError if it is missingNone
pop(i=-1)Removes the item at index ithe removed item
index(x)Finds the position of the first xint
count(x)Counts how often x appearsint
sort() / reverse()Reorders the list in placeNone
clear()Removes every itemNone
copy()Makes a shallow copya new list

append() adds its argument as one item, while extend() adds each item separately:

Python
a = [1, 2]a.append([3, 4])print(a) b = [1, 2]b.extend([3, 4])print(b)
Output
[1, 2, [3, 4]]
[1, 2, 3, 4]

Loop through a list

A for loop visits each item in order. enumerate() gives you the position and the item together, so you do not need a counter variable.

Python
tasks = ["write tests", "run tests", "fix bugs"] for number, task in enumerate(tasks, start=1):    print(f"{number}. {task}")
Output
1. write tests
2. run tests
3. fix bugs

Use in to check whether a value is in a list:

Python
browsers = ["chromium", "firefox", "webkit"]print("firefox" in browsers)print("edge" in browsers)
Output
True
False

Sort a list

Python
scores = [72, 95, 58, 88] print(sorted(scores))          # new sorted listprint(scores)                  # original is unchanged scores.sort(reverse=True)      # sorts in placeprint(scores)
Output
[58, 72, 88, 95]
[72, 95, 58, 88]
[95, 88, 72, 58]
Watch out

scores.sort() changes the list and returns None. Writing scores = scores.sort() throws your list away. Use sorted(scores) when you need a new list.

Pass key= to sort by something other than the value itself, such as the length of each word:

Python
words = ["banana", "fig", "apple"]print(sorted(words, key=len))
Output
['fig', 'apple', 'banana']

Copy a list without surprises

Assigning a list to a new name does not copy it. Both names point at the same list, so a change through one name shows up in the other.

Python
a = [1, 2]b = a            # b is the SAME list, not a copyb.append(3)print(a) c = a.copy()     # c is a new listc.append(4)print(a, c)
Output
[1, 2, 3]
[1, 2, 3] [1, 2, 3, 4]

Check your understanding

Predict the output

x = [1, 2, 3]y = x * 2print(y, len(y))

Quick quiz

1. What does [10, 20, 30][-1] return?

2. Which call removes and returns the last item?

3. After b = a and b.append(3), what is in a?

4. What does [3, 1, 2].sort() evaluate to?

Exercise: remove duplicate emails

You have a list of signup emails with repeats. Build a list that keeps each email once, in the order it first appeared.

Input
["a@x.com", "b@x.com", "a@x.com", "c@x.com", "b@x.com"]
Expected output
['a@x.com', 'b@x.com', 'c@x.com']
Hint 1

A set removes duplicates but does not keep the order.

Hint 2

Dictionary keys are unique and keep insertion order.

Program Practice: Python list programs

Practise what you just learned. Start with the easy programs and work up.

Python lists FAQ

What is the difference between a list and a tuple in Python?

A list is mutable, so you can add, change and remove items. A tuple is immutable: once created, its items cannot change. Use a tuple for fixed data such as coordinates. See List vs Tuple.

How do I check if an item is in a list?

Use the in operator: "apple" in fruits returns True or False.

What is the difference between append() and extend()?

append(x) adds x as one item, even if x is a list. extend(items) adds each item of items separately.

How do I remove duplicates from a list and keep the order?

Use list(dict.fromkeys(items)). list(set(items)) also removes duplicates but does not keep the original order.

Can a Python list hold different data types?

Yes. A list can mix integers, strings, floats, booleans, None and other lists, although lists of one type are easier to work with.

Python If…Else

Python Tutorial › Control Flow › If…Else

Python If…Else

BeginnerLesson 13 of 4711 min read10 runnable examples

Programs need to make decisions: grant access or not, pass or fail, discount or full price. Python makes these decisions with if, elif and else.

In this lesson
  • Run code only when a condition is true
  • Choose between branches with elif and else
  • Nest conditions and combine them
  • Write one-line conditional expressions

The if statement

if runs its indented block only when the condition is true.

Python
temperature = 38 if temperature > 37.5:    print("Fever detected")    print("Please see a doctor")print("Check complete")
Output
Fever detected
Please see a doctor
Check complete

The condition can be any expression. Python treats it as true or false using the truthiness rules from Operators & Booleans.

if … else

else runs when the condition is false. Exactly one of the two blocks runs.

Python
age = 16 if age >= 18:    print("You can vote")else:    print(f"You can vote in {18 - age} years")
Output
You can vote in 2 years

if … elif … else

elif (short for “else if”) checks another condition. Python tests the conditions from top to bottom and runs only the first block whose condition is true.

Python
marks = 74 if marks >= 90:    grade = "A"elif marks >= 75:    grade = "B"elif marks >= 60:    grade = "C"else:    grade = "F" print("Grade:", grade)
Output
Grade: C
Watch out

Order matters. If you test marks >= 60 first, a score of 95 would get “C”, because the first true branch wins and the rest are skipped.

Nested if

An if can sit inside another if. Each level adds 4 spaces of indentation.

Python
username = "admin"password = "s3cret" if username == "admin":    if password == "s3cret":        print("Welcome, admin")    else:        print("Wrong password")else:    print("Unknown user")
Output
Welcome, admin

Deep nesting is hard to read. Often you can flatten it with and:

Python
username, password = "admin", "s3cret" if username == "admin" and password == "s3cret":    print("Welcome, admin")else:    print("Login failed")
Output
Welcome, admin

Combine conditions

Python
day = "Saturday"is_holiday = Falsehour = 22 if day in ("Saturday", "Sunday") or is_holiday:    print("Weekend rates apply") if not is_holiday and 9 <= hour <= 18:    print("Office is open")else:    print("Office is closed")
Output
Weekend rates apply
Office is closed

Conditional expression (one-line if)

For a simple choice between two values, write the condition inline:

Python
stock = 0status = "In stock" if stock > 0 else "Sold out"print(status) n = 7print("even" if n % 2 == 0 else "odd")
Output
Sold out
odd

Empty blocks with pass

A block cannot be empty. Use pass as a placeholder while you are still writing the code:

Python
feature_ready = False if feature_ready:    pass          # TODO: call the new featureelse:    print("Using the old feature")
Output
Using the old feature

Common mistakes

Using = instead of == in a condition is a syntax error:

Python
x = 5if x = 5:    print("five")
Output
  File "main.py", line 2
    if x = 5:
       ^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

x == 1 or 2 does not check whether x is 1 or 2. It means (x == 1) or 2, and 2 is always truthy:

Python
x = 7print(bool(x == 1 or 2))       # always True: a bugprint(x == 1 or x == 2)        # correctprint(x in (1, 2))             # correct and shorter
Output
True
False
False

Check your understanding

Predict the output

n = 15if n % 3 == 0:    print("Fizz")elif n % 5 == 0:    print("Buzz")else:    print(n)

Quick quiz

1. How many branches of an if/elif/else chain run?

2. What does "yes" if 0 else "no" evaluate to?

3. Which correctly tests whether x is 1 or 2?

Exercise: shipping cost

Orders of 500 or more ship free. Otherwise shipping is 40, or 80 for express. Print the shipping cost for each order.

Input
(650, False), (300, False), (300, True)
Expected output
Order 650: shipping 0
Order 300: shipping 40
Order 300: shipping 80
Hint 1

Check the free-shipping rule first.

Program Practice

Python if else FAQ

What is elif in Python?

elif means “else if”. It adds another condition to an if statement and is checked only when all the conditions above it were false.

Does Python have a switch statement?

Python 3.10 added match / case, which covers switch-style logic and much more. See Match Case.

How do I write an if else in one line in Python?

Use a conditional expression: result = "pass" if score >= 50 else "fail".

Can I have an if without an else?

Yes. else is optional. Without it, nothing happens when the condition is false.