Working With Functions

1. Introduction & Understanding Functions

Working With Functions

A function is a named, reusable block of code that performs a specific task. It helps in achieving modularity (dividing a large program into smaller parts) and reusability.

  • Function Types:
    • Built-in Functions: Predefined in Python (e.g., print(), input(), len()).
    • Functions defined in Modules: Available after importing a module (e.g., math.sqrt()).
    • User-defined Functions: Created by the programmer using the def keyword.

2. Defining and Calling Functions

A function definition consists of the header and the body.

Python

def greet(name):          # Function Header
    """Docstring"""       # Optional description
    print("Hello", name)  # Function Body

greet("Alice")            # Function Call/Invocation
  • Parameters: Variables listed in the function definition (e.g., name).
  • Arguments: Actual values passed during the function call (e.g., "Alice").

3. Flow of Execution

Execution always begins at the first statement of the program. When a function call is encountered:

  1. The control jumps to the function definition.
  2. The body of the function is executed.
  3. Control returns to the statement immediately following the function call.

4. Passing Parameters

Python supports various ways to pass arguments:

  • Positional/Required Arguments: Arguments must be provided in the correct positional order.
  • Default Arguments: A parameter can have a default value used if no argument is provided (e.g., def calc(r, pi=3.14):).
  • Keyword (Named) Arguments: Arguments are matched by name, regardless of order (e.g., greet(name="Bob")).

5. Returning Values

Functions use the return statement to send a value back to the caller.

  • Multiple Values: Python functions can return more than one value separated by commas, which are returned as a tuple.Pythondef swap(a, b): return b, a

6. Scope of Variables

Scope determines the portion of the program where a variable is accessible.

  • Local Scope: Variables defined inside a function. They exist only while the function is executing.
  • Global Scope: Variables defined outside all functions. They are accessible throughout the program.
  • LEGB Rule: Python resolves names using the Local -> Enclosed -> Global -> Built-in order.

7. Mutable/Immutable Properties

When passing data to a function:

  • Immutable objects (int, string, tuple): The function receives a copy of the reference. Changes inside the function do not affect the original object (similar to “pass by value”).
  • Mutable objects (list, dictionary): The function can modify the original object directly because it receives a reference to the actual data (similar to “pass by reference”).

===============================================================

Revised Study Material: Working with Functions


3.1 & 3.2 Introduction to Functions

Functions are self-contained blocks of code that perform a specific task. They prevent code duplication and make programs easier to manage.

  • Built-in: print(), len(), type()
  • Modules: math.sin(), random.randint()
  • User-defined: Created by you using def.

3.3 Defining Functions in Python

To define a function, use the def keyword followed by the function name and parentheses.

Example:

Python

def calculate_area(length, breadth):  # Header
    """Calculates area of a rectangle""" # Docstring
    area = length * breadth            # Body
    print("Area is:", area)            # Body

calculate_area(10, 5) # Calling the function

3.4 Flow of Execution

When a program runs, Python follows the statements line by line. However, when a function is called :

  1. The control jumps to the function definition.
  2. The body of the function is executed.
  3. Control returns to the statement immediately following the function call.

3.5 Passing Parameters to function

There are different ways to send information (arguments) to a function:

  • Positional/Required Arguments: Arguments must be provided in the correct positional order.
  • Default Arguments: A parameter can have a default value used if no argument is provided (e.g., def calc(r, pi=3.14):).
  • Keyword (Named) Arguments: Arguments are matched by name, regardless of order (e.g., greet(name="Bob")).

3.5.1 Positional Arguments

The values are assigned to parameters based on their position.

Python

def check_grade(name, marks):
    print(name, "scored", marks)

check_grade("Amit", 90) # Correct
check_grade(90, "Amit") # Logical Error: position matters

3.5.2 Default Arguments

You can assign a default value to a parameter in the header. If the caller doesn’t provide a value, the default value is used by the function.

Python

def greet(name, msg="Good Morning"):
    print("Hello", name, msg)

greet("Sumit")                 # Uses default: Hello Sumit Good Morning
greet("Sumit", "How are you?") # Overrides default: Hello Sumit How are you?

3.5.3 Keyword (Named) Arguments

You can specify the parameter name during the call to ignore the position/order of the parameters.

def interest(principal, rate, time):
    return (principal * rate * time) / 100

# Order doesn't matter if names are used
print(interest(rate=8, time=2, principal=1000))

3.6 Returning Values

A function can send a result back to the main program using the return statement.

def get_stats(numbers):
    high = max(numbers)
    return high

max_val = get_stats([10, 20, 30])
print(max_val)

Returning Multiple Values:

Python can also return multiple values as a tuple.

def get_stats(numbers):
    high = max(numbers)
    low = min(numbers)
    return high, low # Returns a tuple (high, low)

max_val, min_val = get_stats([10, 20, 30])

3.8 Scope of Variables

Scope defines where a variable can be “seen” or used. Scope determines the portion of the program where a variable is accessible.

  • Local Scope: Variables defined inside a function. They exist only while the function is executing.
  • Global Scope: Variables defined outside all functions. They are accessible throughout the program.
x = 10 # Global

def my_func():
    y = 5 # Local
    print(x) # Accessible
    print(y) # Accessible

my_func()
# print(y) # Error: y is not defined outside the function

LEGB Rule:

Python resolves names using the following order:

Local -> Enclosed -> Global -> Built-in

The LEGB rule in Python explains how variable names are resolved (searched) when you use them in code.

LEGB stands for:

  1. L — Local
  2. E — Enclosing
  3. G — Global
  4. B — Built-in

Python searches for variables in this order.


1. Local Scope (L)

Variables defined inside a function.

def my_func():
    x = 10   # local variable
    print(x)

my_func()

Output:

10

Here, x exists only inside my_func().


2. Enclosing Scope (E)

Variables in an outer function enclosing an inner function.

def outer():
    x = 20   # enclosing variable

    def inner():
        print(x)

    inner()

outer()

Output:

20

inner() cannot find x locally, so it checks the enclosing function outer().


3. Global Scope (G)

Variables defined outside all functions.

x = 30   # global variable

def my_func():
    print(x)

my_func()

Output:

30

Python checks global scope if not found locally or enclosing.


4. Built-in Scope (B)

Python’s predefined names/functions like print(), len(), sum().

numbers = [1, 2, 3]

print(len(numbers))

Output:

3

len is found in Python’s built-in scope.


Full LEGB Example

x = "Global"

def outer():
    x = "Enclosing"

    def inner():
        x = "Local"
        print(x)

    inner()

outer()

Output:

Local

Python finds x in Local scope first.


Another Example Showing Search Order

x = "Global"

def outer():

    x = "Enclosing"

    def inner():
        print(x)

    inner()

outer()

Output:

Enclosing

Search order:

  • Local → not found
  • Enclosing → found

So Python prints "Enclosing".


Important Note: global and nonlocal

Using global

If you want to modify a global variable inside a function, you must use the global keyword.

x = 5

def change():
    global x
    x = 100

change()
print(x)

Output:

100

Using nonlocal

def outer():
    x = 10

    def inner():
        nonlocal x
        x = 50

    inner()
    print(x)

outer()

Output:

50

LEGB Search Flow

When Python sees a variable:

Local → Enclosing → Global → Built-in

The first match found is used.

3.9 Mutable/Immutable Properties of Arguments

This is a critical concept for exams. It dictates whether a function can change the original variable passed to it.

  • Immutable (Integers, Strings, Tuples): Changes inside the function do not reflect in the original variable.
  • Mutable (Lists, Dictionaries): Changes inside the function do reflect in the original variable.

Example with a List (Mutable):

def modify_list(lst):
    lst.append(100) # Changes the original list
    print("Inside function:", lst)

my_list = [1, 2, 3]
modify_list(my_list)
print("Outside function:", my_list) # Output: [1, 2, 3, 100]

=================================================——



2. Mutable vs. Immutable Properties

This concept determines if the “original” data changes when passed as an argument.

A. Immutable Objects (Integers, Strings, Tuples)

When you pass an immutable object, the function creates a local copy. The original remains unchanged.

Python

def increment(n):
    n += 1
    print("Value inside function:", n)

val = 10
increment(val)
print("Value outside function:", val)

Output:

Value inside function: 11

Value outside function: 10

B. Mutable Objects (Lists, Dictionaries)

When you pass a list or dictionary, the function receives a reference to the actual memory location. Any changes made inside the function affect the original object.

Python

def add_item(my_list):
    my_list.append("New Item")
    print("List inside:", my_list)

fruits = ["Apple", "Banana"]
add_item(fruits)
print("List outside:", fruits)

Output:

List inside: [‘Apple’, ‘Banana’, ‘New Item’]

List outside: [‘Apple’, ‘Banana’, ‘New Item’]


Comparison Table for Quick Revision

FeatureLocal ScopeGlobal Scope
DefinedInside a functionOutside all functions
LifetimeDeleted when function endsExists until program ends
AccessibilityOnly inside that functionAccessible everywhere
Data TypePropertyEffect of Function Modification
Int, String, TupleImmutableOriginal value never changes
List, DictionaryMutableOriginal value does change

===============================================================

Questions for Practice

Section A: Variable Scope (LEGB Rule)

Question 1

What will be the output of the following Python code?

Python

val = 20
def display():
    val = 10
    print(val, end=" ")

display()
print(val)
  • Concepts tested: Local vs. Global scope.

Question 2

Identify the error in the following code snippet and suggest the correction:

Python

count = 0
def increment():
    count = count + 1
    print(count)

increment()
  • Concepts tested: Modifying a global variable inside a local scope.

Question 3

What will be the output of the following code?

Python

def outer():
    x = "local"
    def inner():
        nonlocal x
        x = "nonlocal"
        print("inner:", x)
    inner()
    print("outer:", x)

outer()
  • Concepts tested: Nested functions and the nonlocal keyword.

Section B: Mutable vs. Immutable Properties

Question 4

Predict the output of the following code:

Python

def process(a):
    a = a + [10]
    print("Inside:", a)

my_list = [1, 2, 3]
process(my_list)
print("Outside:", my_list)
  • Concepts tested: Behavior of lists during reassignment (concatenation) versus in-place modification.

Question 5

What will the following code print?

Python

def change_data(data):
    data[1] = 99
    data = [4, 5, 6]

numbers = [1, 2, 3]
change_data(numbers)
print(numbers)
  • Concepts tested: Mutable object modification via indexing vs. variable reassignment.

Question 6

Consider the following function. What is the output?

Python

def update_str(s):
    s = s + " World"
    return s

msg = "Hello"
update_str(msg)
print(msg)
  • Concepts tested: Immutability of strings.

Section C: Mixed Concepts (Advanced)

Question 7

Trace the output of this code carefully:

Python

def func(p, q=10):
    p = p + q
    q = p - q
    print(p, "#", q)
    return p

r = 5
r = func(r)
print(r)
  • Concepts tested: Default arguments, arithmetic updates, and return values.

Question 8

Analyze the following code and write the output:

Python

def my_func(a):
    a.append(a[0])
    a[0] = 5

v = [1, 2]
my_func(v)
print(v)
  • Concepts tested: List methods and in-place mutation.

Question 9:

Identify the valid/invalid function call statement(s)

def add(n1,n2,n3=5):
    return n1+n2+n3

result1=add(6,7,8) 
result2=add(5) 
result3=add(4,8,n1=5) 
result4=add(2,9, n3=88)
result5=add(n2=6,n1=7) 
result6=add(n1=10, 5, 6) 

In Python, function calls must follow specific rules regarding positional arguments (values passed in order) and keyword arguments (values assigned to specific names).

Answer:

StatementStatusReason
result1=add(6,7,8)ValidPasses three positional arguments. n1=6, n2=7, and n3 is overridden from 5 to 8.
result2=add(5)InvalidMissing argument. The function requires at least two arguments (n1 and n2). Only n3 has a default value.
result3=add(4,8,n1=5)InvalidMultiple values for ‘n1’. The first positional argument 4 is already assigned to n1. You cannot assign to it again via keyword.
result4=add(2,9, n3=88)ValidCorrect use of positional arguments for n1 and n2, and a keyword argument to override n3.
result5=add(n2=6,n1=7)ValidCorrect use of keyword arguments. Since they are named, the order doesn’t matter. n3 will use its default value of 5.
result6=add(n1=10, 5, 6)InvalidSyntax Error. Positional arguments (5, 6) cannot follow keyword arguments (n1=10). All positional arguments must come first.

Summary of Key Rules

  1. Required vs. Optional: Arguments without default values (like n1 and n2) are mandatory.
  2. The Order Rule: Once you use a keyword argument (e.g., name=value), you cannot go back to using plain positional arguments in that same call.
  3. No Double Dipping: You cannot provide a value for the same parameter more than once.

Question 10:

You have a function defined as follows:

def calc_vol(length, width, height=10, scale=1):
    return (length * width * height) * scale

Identify which of the following calls are Valid or Invalid and state the reason why.

A) calc_vol(2, 3)

B) calc_vol(width=5, length=2)

C) calc_vol(2, width=3, 5)

D) calc_vol(length=2, 3, height=5)

E) calc_vol(2, 3, height=5, 2)

F) calc_vol(4, 5, length=2)

G) calc_vol(2, 4, scale=0.5)

H) calc_vol(width=10)

I) calc_vol(1, 2, 3, 4)

Answer:

Call StatementStatusReason
A) calc_vol(2, 3)Validlength=2, width=3. Uses defaults for height (10) and scale (1).
B) calc_vol(width=5, length=2)ValidKeyword arguments can be provided in any order.
C) calc_vol(2, width=3, 5)InvalidSyntax Error: Positional arguments cannot follow keyword arguments.
D) calc_vol(length=2, 3, height=5)InvalidSyntax Error: Again, the positional 3 appears after a keyword argument.
E) calc_vol(2, 3, height=5, 2)InvalidSyntax Error: A positional argument (2) follows a keyword argument (height=5).
F) calc_vol(4, 5, length=2)InvalidMultiple Values: 4 is assigned to length positionally, but length=2 tries to assign to it again.
G) calc_vol(2, 4, scale=0.5)ValidSkips the default height and provides a specific scale.
H) calc_vol(width=10)InvalidMissing Argument: length is a required positional/keyword argument and was not provided.
I) calc_vol(1, 2, 3, 4)ValidOverwrites all defaults using positional ordering.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top