Controlling the flow of execution in Python programming

By Abhinash Jena on December 16, 2024

Computers execute programs by following instructions or codes written in a program step by step, just like reading a book. The instructions are executed by the computer’s CPU, memory, and other hardware components. In Python programming, control flow dictates the sequence in which these instructions are executed.

It determines whether instructions should:

  • Run sequentially.
  • Skipped.
  • Repeated.
  • Conditioned on specific criteria.

Control flow provides the logic that governs how a program behaves during execution. Without it, all instructions would execute in a fixed, rigid sequence, making dynamic or responsive programs impossible.

Program execution in a sequential flow

Sequential Flow is the simplest form of program execution where instructions are executed one after the other, in the exact order they appear in the program. The instructions are executed line by line. Such programs cannot handle complex tasks that require decision-making or repetition.

Name = input('Enter your name: ') 

Print('Hello, ' + name)

>> Enter your name: Project Guru
Hello, Project Guru

Each line is executed once, and the program terminates after completing the sequence. It is like reading a book from start to finish, without skipping chapters, rereading sections, or jumping to different parts. The computer executes instructions from top to bottom in a linear fashion. While programs with sequential flow work well for static, linear tasks, most real-world problems require conditional logic and loops.

Controlling program execution with a conditional flow

In conditional flow, instructions are executed based on conditions using statements like if, elif and else. A conditional flow gives the computers the ability to make decisions based on specific criteria. Programs can execute different sets of instructions depending on whether certain conditions are true or false. This flexibility is essential for building dynamic and responsive systems. In a conditional flow, a logical test evaluates to either true or false. Based on the result, a specific block of code is executed.

EXAMPLE

Think of traffic lights. If the light is green, you proceed, else if the light is yellow, you slow down. Otherwise, you stop. As there are three coloured lights, it can be assumed that by default the third case is red.

light = input('Enter colour: ')

if light == "green":
  print("Go")
elif light == "yellow":
  print("Slow down")
else:
  print("Stop")

>> Enter colour: red
Stop

Logical tests in conditional statements rely on operators such as == to compare values and make decisions based on the results. These operators compare two values and return true or false based on the condition.

OperatorMeaning ExampleResult
== Equal to 5 == 5TRUE
!= Not equal to 5 != 3TRUE
> Greater than 5 > 3TRUE
< Less than 5 < 3FALSE
>= Greater than or equal to 5 >= 5TRUE
<= Less than or equal to 3 <= 5TRUE
A list of useful operators for conditional statements in Python programming

Logical tests in conditional statements can also combine multiple tests.

Operator MeaningExampleResult
and Returns True if both conditions are true (5 > 3) and (2 < 4)TRUE
or Returns True if at least one condition is true (5 > 3) or (2 > 4)TRUE
not Negates the result of a condition not(5 > 3)FALSE
Combination of logical tests in a conditional statement in Python programming
is_sunday = True 

is_holiday = True

if is_sunday and is_holiday:

  print ("Go for a movie.")
Go for a movie.

Furthermore, there are membership operators that check if a value is part of a sequence like a list, string, or tuple.

OperatorMeaningExample Result
in Checks if a value is present "apple" in ["apple", "orange"]TRUE
not in Checks if a value is absent "banana" not in ["apple", "orange"]TRUE
Membership operators for conditional statements in Python programming
fruits = ["apple", "banana", "cherry"] 

if "apple" in fruits:

  print ("Apple is available.")
Apple is available.

Likewise, identity operators also compare objects to see if they are the same in memory.

OperatorMeaningExampleResult
is Check if objects are the samea is bCheck if objects are the same
is not Checks if objects are different a is not bTrue or False
Identity operators for conditional statements in Python programming
a = [1, 2, 3] 

b = [4, 5, 6]

c = a

print (a is b) # (different objects)

print (a is c) # (same object)
False
True

Conditional flow is the cornerstone of logical decision-making in programming. By allowing programs to adapt to different conditions dynamically, it bridges the gap between static instructions and real-world complexities.

Automating repetitive Python programming tasks with iterative flow

While conditional flow (if, elif, else) allows programs to make decisions based on conditions, it is not designed for repetitive tasks or handling large datasets efficiently. In conditional flow, performing the same task multiple times requires writing the same code repeatedly. This leads to redundancy, longer code, and increased chances of errors.

print (1) 

print (2)

print (3)
1
2
3

Loops like for can automate such repetitive tasks.

for i in range(1, 4): 

  print(i)
1
2
3
TIP

The range (start, stop, step) function is a built-in Python function that generates a sequence of numbers.

for loop is also used to iterate over a sequence like a list or tuple and execute a block of code for each element.

fruits = ["apple", "banana", "cherry"] 

for fruit in fruits:

  print(fruit)
apple
banana
cherry
TIP

Use continue to skip execution of the rest of the code in the loop block.

fruits = ["apple", "banana", "cherry"] 

for fruit in fruits:

  if (fruit == 'banana'):

    continue

print(fruit)
apple
cherry

for loops are used to iterate finite sequences or ranges, it cannot handle unknown termination. Loops like while allow dynamic termination based on a condition.

i = 0 

while i < 5:

  print(i)

  i += 1

Although while loops are ideal for tasks where the number of iterations is not known beforehand, it will run into infinite loops if the termination condition is not met or properly mentioned. Infinite loops theoretically can run forever unless interrupted. It is often used for event-driven programs.

TIP

To exit a loop prematurely you can also use break. Once break is executed, the program immediately jumps out of the loop and resumes execution at the next line after the loop block.

x = 1;

While true:

  print(x)

  x = x + 1

  if(x > 3):

    break

print ('Execution completed.')
1
2
3
Execution completed.

Reusing blocks of codes with functions in Python programming

Functions play a critical role in programming by encapsulating logic. It is a reusable block of code designed to perform a specific task. It allows programmers to organize code into modular units, improving readability, reusability, and efficiency. Functions help to break large programs into smaller, manageable parts.

def greet(name): 

  return f"Hello, {name}!"

print(greet("Alice"))
Hello, Alice!
TIP

return is to send the result of its computation back to the caller. It effectively ends the function execution and specifies what value (if any) should be returned to the code that called the function. Both print() & return are used as output methods. return gives values to be used elsewhere in the program, while print simply shows values to the user.

Without functions, programs become redundant as the same block of code might need to be written multiple times. Furthermore, programs written without functions become large and unmanageable. Also, programs with repeated logic waste memory and processing time.

Without using a function

length1, width1 = 10, 5

length2, width2 = 7, 3

print(length1 * width1)

print(length2 * width2)
50
21

Using a function

def area(length, width):

  return length * width

print(area(10, 5))

print(area(7, 3))
50
21

A step towards efficient programming using iterators and generators

An iterator is an object that allows traversal through elements in a collection, such as a list or tuple, one element at a time. Iterators allow efficient access to data without loading the whole collection into memory at once.

Key characteristics of iterators:

  • They implement two methods: __iter__() and __next__().
  • They remember their state and know which element comes next.
  • They raise a StopIteration exception when there are no more elements.
list = [1, 2, 3, 4, 5] 

iterator = iter(list)

print(next(iterator))

print(next(iterator))
1
2

Likewise, a generator is a special type of iterator that lazily produces values one at a time using yield.

def generate_numbers(): 

  for i in range(1, 4):

    yield i

for num in generate_numbers():

  print(num) 
1
2
3
NOTE

Generator functions are different from regular functions. While regular functions return and terminate immediately, generators use yield to pause execution and resume when called again.

Lists can be iterated within loops but iterating through large lists such as containing one million elements can be memory intensive and may also result in memory outage. This is because iterating using a loop with list comprehensions shall load all values into the memory at once. Whereas generators return values on-demand, which is ideal for handling:

  • infinite sequences,
  • streaming data,
  • mathematical sequences

Generators create demand values which makes them memory-efficient. The primary advantage of generators is their ability to work with large or infinite sequences without consuming excessive memory, making them powerful for data processing, mathematical sequences, and handling large files.

# Memory-intensive approach

def intensive_approach (n): 

  result = []

  for i in range(n):

    result.append(i ** 2)

  return result

# Memory-efficient generator

def efficient _approach (n):

  for i in range(n):

     yield i ** 2

# Function creates entire sequence in memory

large_list = intensive_approach (1000000)

# Generator creates values on-the-fly

large_generator = efficient _approach (1000000)

Unlike regular functions, generators can maintain their internal states between calls and iterations.

Think of a regular function like a vending machine that resets to its initial state each time you insert money:

  • Always starts from the same point.
  • No memory of previous transactions.

Whereas a generator is a smart vending machine that:

  • Remembers, how many items have been dispensed.
  • Tracks inventory.
  • Can be paused and resumed.
def fibonacci_generator(): 

  # Maintains multiple state variables

  a, b = 0, 1

  while True:

    # Yields current state, prepares next state

    yield a

  a, b = b, a + b

# Creates a stateful fibonacci sequence generator

fib = fibonacci_generator()

print(next(fib))

print(next(fib))

print(next(fib))

print(next(fib))

print(next(fib))
0
1
1
2
3

The internal state of generators provides a unique way to create stateful, pausable computations that remembers their exact point of execution and can be dynamically controlled.

NOTES

I am an interdisciplinary educator, researcher, and technologist with over a decade of experience in applied coding, educational design, and research mentorship in fields spanning management, marketing, behavioral science, machine learning, and natural language processing. I specialize in simplifying complex topics such as sentiment analysis, adaptive assessments and data visualizatiion. My training approach emphasizes real-world application, clear interpretation of results and the integration of data mining, processing, and modeling techniques to drive informed strategies across academic and industry domains.

Discuss

3 thoughts on “Controlling the flow of execution in Python programming”