Close Menu
TechBeamersTechBeamers
    TechBeamersTechBeamers
    • Python
    • Java
    • C
    • SQL
    • MySQL
    • Selenium
    • Testing
    • Agile
    • Linux
    • WebDev
    • Technology
    TechBeamersTechBeamers
    Python Basic

    Python Functions Explained

    By Meenakshi AgarwalUpdated:Nov 23, 2023No Comments16 Mins Read
    Share
    Facebook Twitter LinkedIn Pinterest Email

    This tutorial walks you through the concept of Python functions. It helps you learn how to create user-defined functions and use them to write modular programs in Python.

    What is a Python Function, How to Create and Call?

    A function in Python is an independent and reusable block of code that you can call any number of times from any place in a program. It is an essential tool for programmers to split a big project into smaller modules. Here are some key points to consider.

    1. They are the core building blocks of any programming language that a programmer must learn to use. Python provides a number of built-in methods for direct use and also allows you to define your custom functions.

    2. A function in Python is a logical unit of code containing a sequence of statements indented under a name given using the “def” keyword.

    3. Functions allow you to create a logical division of a big project into smaller modules. They make your code more manageable and extensible.

    4. While programming, a function prevents you from adding duplicate code and promotes reusability.

    Let’s now quickly see what else are we going to learn from this tutorial.

    How to Create a Function – Syntax

    The syntax of a Python function is as follows.

    Single line function:

    def single_line(): statement

    Python function with docstring:

    def fn(arg1, arg2,...):
        """docstring"""
        statement1
        statement2

    Nested Python function:

    def fn(arg1, arg2,...):
        """docstring"""
        statement1
        statement2
        def fn_new(arg1, arg2,...):
            statement1
            statement2
            ...
        ...

    Def Statement

    Please read the below notes before creating your first Python function.

    • The “def” keyword is a statement for defining a function in Python.
    • You start a function with the def keyword and specify a name followed by a colon (:) sign.
    • The “def” call creates the function object and assigns it to the name given.
    • You can further re-assign the same function object to other names.
    • Give a unique name to your function and follow the same rules as naming the identifiers.
    • Add a meaningful docstring to explain what the function does. However, it is an optional step.
    • Now, start the function body by adding valid Python statements each indented with four spaces.
    • You can also add a statement to return a value at the end of a function. However, this step is optional.
    • Just press enter and remove the indentation to end a function.
    • Since def is a statement, you can use it anywhere a statement can appear – such as nested in an if clause or within another function.

    Example :

    if test:
            def test(): # First definition
                ...
        else:
            def test(): # Alternate definition
                ...
        ...

    How to Call a Function in Python?

    By using the def keyword, you learned to create the blueprint of a function that has a name, parameters to pass, and a body with valid Python statements.

    The next step is to execute it. You can do so by calling it from the Python script, inside a function, or directly from the Python shell.

    To call a function, you need to specify the function name with relevant parameters, and that’s it.

    Follow the below example to learn how to call a function in Python.

    Python function for modular programming

    Example of a Function Call

    It’s a simple example where a function “typeOfNum()” has nested functions to decide if a number is either odd or even.

    def typeOfNum(num): # Function header
        # Function body
        if num % 2 == 0:
            def message():
                print("You entered an even number.")
        else:
            def message():
                print("You entered an odd number.")
        message()
    # End of function
    
    typeOfNum(2)  # call the function
    typeOfNum(3)  # call the function again

    Polymorphism in Python

    In Python, function polymorphism is possible as we don’t specify the argument types while creating functions.

    • The behavior of a function may vary depending on the arguments passed to it.
    • The same function can accept arguments of different object types.
    • If the objects find a matching interface, the function can process them.

    Example :

    def product(x, y) : return x * y
    print(product(4, 9)) # function returns 36
    print(product('Python!', 2))  # function returns
                                  # Python!Python!
    print(product('Python 2 or 3?', '3')) # TypeError occurs

    The above example clarifies that we can pass any two objects to the product() function which supports the ‘*’ operator.

    The concept above we’ve explained is known as polymorphism. Some points which you should remember are as follows.

    • Python is a dynamically typed language which means the types correlate with values, not with variables. Hence, the polymorphism runs unrestricted.
    • That’s one of the primary differences between Python and other statically typed languages such as C++ or Java.
    • In Python, you don’t have to mention the specific data types while coding.
    • However, if you do, then the code limits to the types anticipated at the time of coding.
    • Such code won’t allow other compatible types that may be required in the future.
    • Python doesn’t support any form of function overloading.
    See also  Class Definitions in Python

    Parameters in a Function

    We often use the terms parameters and arguments interchangeably. However, there is a slight difference between them.

    Parameters are the variables used in the function definition whereas arguments are the values we pass to the function parameters.

    Python supports different variations of passing parameters to a function. Before we discuss each of them, you should read the following notes.

    • The argument gets assigned to the local variable name once passed to the function.
    • Changing the value of an argument inside a function doesn’t affect the caller.
    • If the argument holds a mutable object, then changing it in a function impacts the caller.
    • We call the passing of immutable arguments as Pass by Value because Python doesn’t allow them to change in place.
    • The passing of mutable arguments happens to be Passed by Pointer in Python because they are likely to be affected by the changes inside a function.

    Example: Immutable vs. Mutable

    def test1(a, b) :
        a = 'Garbage' # 'a' receives an immutable object
        b[0] = 'Python' # 'b' receives a list object
                        # list is mutable
                        # it can undergo an in place change
    def test2(a, b) :
        a = 'Garbage 2'
        b = 'Python 3' # 'b' now is made to refer to new
                       # object and therefore argument 'y'
                       # is not changed
    
    arg1 = 10
    arg2 = [1, 2, 3, 4]
    test1(arg1, arg2)
    print("After executing test 1 =>", arg1, arg2)
    test2(arg1, arg2)
    print("After executing test 2 =>", arg1, arg2)

    After execution, the above code prints the following.

    After executing test 1 => 10 ['Python', 2, 3, 4]
    After executing test 2 => 10 ['Python', 2, 3, 4]

    Example: How to avoid changing the mutable argument

    def test1(a, b) :
        a = 'Garbage'
        b[0] = 'Python'
    
    arg1 = 10
    arg2 = [1, 2, 3, 4]
    
    print("Before test 1 =>", arg1, arg2)
    test1(arg1, arg2[:]) # Create an explicit copy of mutable object
                         # 'y' in the function.
                         # Now 'b' in test1() refers to a
                         # different object which was initially a
                         # copy of 'arg2'
                                
    print("After test 1  =>", arg1, arg2)

    After execution, the above code prints the following.

    Before test 1 => 10 [1, 2, 3, 4]
    After test 1  => 10 [1, 2, 3, 4]

    Standard arguments

    The standard arguments are those that you pass as specified in a Python function definition. It means without changing their order and without skipping any of them.

    def fn(value):
        print(value)
        return
    
    fn()

    Executing the above code throws the below error as we’ve not passed the single argument required.

    TypeError: fn() missing 1 required positional argument: 'value'

    Keyword-based arguments

    When you assign a value to the parameter (such as param=value) and pass it to the function (like fn(param=value)), then it turns into a keyword argument.

    If you pass the keyword arguments to a function, then Python determines it through the parameter name used in the assignment.

    See the below example.

    def fn(value):
        print(value)
        return
    
    fn(value=123) # output => 123
    fn(value="Python!") # output => Python!

    While using keyword arguments, you should make sure that the name in the assignment should match the one in the function definition. Otherwise, Python throws the TypeError as shown below.

    fn(value1="Python!") # wrong name used in the keyword argument

    The above function call causes the following error.

    TypeError: fn() got an unexpected keyword argument 'value1'

    Arguments with Default Values

    Python functions allow setting the default values for parameters in the function definition. We refer to them as the default arguments.

    The callee uses these default values when the caller doesn’t pass them in the function call.

    The below example will help you clearly understand the concept of default arguments.

    def daysInYear(is_leap_year=False):
        if not is_leap_year:
            print("365 days")
        else:
            print("366 days")
        return
    
    daysInYear()
    daysInYear(True)

    Here, the parameter “is_leap_year” is working as a default argument. If you don’t pass any value, then it assumes the default which is False.

    The output of the above code is:

    365 days
    366 days

    Variable Arguments

    You may encounter situations when you have to pass additional arguments to a Python function. We refer to them as variable-length arguments.

    See also  Copy Module in Python

    Python’s print() is itself an example of such a function that supports variable arguments.

    To define a function with variable arguments, you need to prefix the parameter with an asterisk (*) sign. Follow the below syntax.

    def fn([std_args,] *var_args_tuple ):
       """docstring"""
       function_body
       return_statement

    Check out the below example for better clarity.

    def inventory(category, *items):
        print("%s [items=%d]:" % (category, len(items)), items)
        for item in items:
            print("-", item)
        return
    
    inventory('Electronics', 'tv', 'lcd', 'ac', 'refrigerator', 'heater')
    inventory('Books', 'python', 'java', 'c', 'c++')

    The output of the above code goes like this.

    Electronics [items=5]: ('tv', 'lcd', 'ac', 'refrigerator', 'heater')
    - tv
    - lcd
    - ac
    - refrigerator
    - heater
    Books [items=4]: ('python', 'java', 'c', 'c++')
    - python
    - java
    - c
    - c++

    Please note that you can choose to have a formal argument or not in the function definition along with the variable arguments.

    You may choose to skip the variable arguments while calling the function. In such a case, the tuple would remain empty.

    Local Variables inside a Function

    A local variable has visibility only inside a code block such as the function def.

    They are available only while the function is executing.

    Check out the below example of using local variables.

    def fn(a, b) :     
        temp = 1
        for iter in range(b) :
            temp = temp*a
        return temp
    
    print(fn(2, 4))
    
    print(temp) # error : can not access 'temp' out of scope of function 'fn'
    print(iter) # error : can not access 'iter' out of scope of function 'fn'

    In this example, we try to access local variables outside the function body which results in the NameError.

    The function’s local variables don’t retain values between calls. The names used inside a def do not conflict with variables outside the def, even if you’ve used the same names elsewhere.

    In Python, the variables assignment can occur at three different places.

    • Inside a def – it is local to that function
    • In an enclosing def – it is nonlocal to the nested functions
    • Outside all def(s) – it is global to the entire file

    Global Variables in a Function

    The global keyword is a statement in Python. It enables variables (names) to retain changes that live outside a def, at the top level of a module file.

    In a single global statement, you can specify one or more names separated by commas.

    All the listed names are attached to the enclosing module’s scope when assigned or referenced within the function body.

    Check the below example.

    x = 5
    y = 55
    def fn() :
        global x
        x = [3, 7]
        y = [1, 33, 55]
        # a local 'y' is assigned and created here
        # whereas, 'x' refers to the global name
    fn()
    print(x, y)

    In the above code, ‘x’ is a global variable that will retain any change in its value made in the function. Another variable ‘y’ has local scope and won’t carry forward the change.

    Let’s now see how a globally declared name behaves in two different Python functions.

    foo = 99
    
    def fn1() :
        foo = 'new' # new local foo created
    
    def fn2() :
        global foo
        foo = 'update' # value of global foo changes

    In the next example, let’s see how global behaves with the import statement.

    Here, we have the following three scripts:

    • mod_global.py: It contains the global definition and a function changing and displaying values.
    • test1.py: It imports the first file and accesses the global variable.
    • test2.py: It uses the “from” clause to import the first file and access the global variable.
    # mod_global.py
    def fn1() :
       global x	
       x = [1,2] ; y = [20, 200]
       # a local 'y' is created – availableonly within 'f1'
       # 'x' can be accessed anywhere after a call to 'f1'
    fn1()
    try :
        print(x, y) # name 'y' is not defined – error
    except Exception as ex:
        print('y ->', ex)
        print('x ->', x)
    # test1.py
    import mod_global
    print('test1 ->', mod_global.x)
    # test2.py
    from mod_global import *
    print('test2 ->', x)

    Name Resolution in a Python Function

    It is essential to understand how name resolution works in case of a def statement.

    Here are a few points you should keep in mind.

    • The name assignments create or change local names.
    • The LEGB rule comes in the picture for searching the name reference.
      • local – L
      • then enclosing functions (if any) – E
      • next comes the global – G
      • and the last one is the built-in – B

    To gain more understanding, run through the below example.

    #var = 5
    def fn1() :
       #var = [3, 5, 7, 9]
       def fn2() :
          #var = (21, 31, 41)
          print(var)
       fn2()
    fn1()	# uncomment var assignments one-by-one and check the output
    print(var)

    After uncommenting the first “var” assignment, the output is:

    5
    5

    Next, after uncommenting the second “var” assignment as well, the output is:

    [3, 5, 7, 9]
    5

    Finally, if we uncomment the last “var” assignment, then the result is as follows.

    (21, 31, 41)
    5

    Scope Lookup in Functions

    Python functions can access names in all available enclosing def statements.

    See also  Python Keywords, Identifiers, and Variables

    Check the below example.

    X = 101 # global scope name - unused
    def fn1():
       X = 102 # Enclosing def local
       def fn2():
          print(X) # Reference made in nested def
       fn2() # Prints 102: enclosing def local
    fn1()

    The scope lookup remains in action even if the enclosing function has already returned.

    def fn1():
       print('In fn1')
       X = 100
       def fn2(): 
          print('In fn2')
          print(X) # Remembers X in enclosing def scope
       return fn2 # Return fn2 but don't call it
    action = fn1() # Make, return function
    action() # Call fn2() now: prints 100

    The output is as follows.

    In fn1
    In fn2
    100

    Return Values from a Python Function

    In Python functions, you can add the “return” statement to return a value.

    Usually, the functions return a single value. But if required, Python allows returning multiple values by using the collection types such as using a tuple or list.

    This feature works like the call-by-reference by returning tuples and assigning the results back to the original argument names in the caller.

    def returnDemo(val1, val2) :
       val1 = 'Windows'
       val2 = 'OS X'
       return val1, val2 # return multiple values in a tuple
    
    var1 = 4
    var2 = [2, 4, 6, 8]
    
    print("before return =>", var1, var2)
    var1, var2 = returnDemo(var1, var2)
    print("after return  =>", var1, var2)

    The above code gives the following output.

    before return => 4 [2, 4, 6, 8]
    after return => Windows OS X

    Python Function Examples

    Check out a general function call example.

    def getMin(*varArgs) :
        min = varArgs[0]
        for i in varArgs[1:] :
            if i < min :
                min = i
        return min
    
    min = getMin(21, -11, 17, -23, 6, 5, -89, 4, 9)
    print(min)

    The output is as follows.

    -89

    Next is an example of the recursive function.

    def calcFact(num) :
        if(num != 1) :
            return num * calcFact(num-1)
        else :
            return 1
    
    print(calcFact(4))

    The output is as follows.

    24

    Also Read: Higher Order Functions in Python

    Python Functions as Objects

    Yes, Python treats everything as an object and functions are no different.

    You can assign a function object to any other name.

    def testFunc(a, b) : print('testFunc called')
    fn = testFunc
    fn(22, 'bb')

    The output is:

    testFunc called

    You can even pass the function object to other functions.

    def fn1(a, b) : print('fn1 called')
    def fn2(fun, x, y) : fun(x, y)
    fn2(fn1, 22, 'bb')

    The output is:

    fn1 called

    You can also embed a function object in data structures.

    def fn1(a) : print('fn1', a)
    def fn2(a) : print('fn2', a)
    
    listOfFuncs = [(fn1, "First function"), (fn2, "Second function")]
    for (f, arg) in listOfFuncs : f(arg)

    The output is:

    fn1 First function
    fn2 Second function

    You can return a function object from another function.

    def FuncLair(produce) :  
        def fn1() : print('fn1 called')
        def fn2() : print('fn2 called')
        def fn3() : print('fn3 called')
        if produce == 1 : return fn1
        elif produce == 2 : return fn2
        else : return fn3
    
    f = FuncLair(2) ; f()

    The output is:

    fn2 called

    Function Attributes

    Python functions also have attributes.

    • You can list them via the dir() built-in function.
    • The attributes can be system-defined.
    • Some of them can be user-defined as well.
    • The dir() function also lists the user-defined attributes.
    def testFunc():
        print("I'm just a test function.")
    
    testFunc.attr1 = "Hello"
    testFunc.attr2 = 5
    testFunc()
    print(dir(testFunc))

    The output is:

    I'm just a test function.
    ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'attr1', 'attr2']

    You can utilize the function attributes to archive state information instead of using any of the globals or nonlocal names.

    Unlike the nonlocals, attributes are accessible anywhere the function itself is, even from outside its code.

    Summary – Python Function

    We’ve covered every essential concept of a Python function in this tutorial. You should now try to use these concepts in your routine programming tasks.

    If you found it useful, then do share it with your colleagues. Also, you may connect to our social media accounts to receive timely updates.

    Best,

    TechBeamers

    Previous ArticlePython If Else Explained
    Next Article How to Use Python Lambda with Map, filter, Data Science, and Pandas
    Meenakshi Agarwal

    I'm Meenakshi Agarwal, founder of TechBeamers.com, with 10+ years of experience in Software development, testing, and automation. Proficient in Python, Java, Selenium, SQL, & C-Sharp, I create tutorials, quizzes, exercises and interview questions on diverse tech topics. Follow my tutorials for valuable insights!

    Add A Comment

    Leave A Reply Cancel Reply

    Python Coding Exercises for Beginners
    • 40 Python Exercises for Beginners
    • 6 Python Data Class Exercises
    • 100+ Python Interview Questions for 2024
    • 20 Python Programs to Print Patterns
    Python Basic Tutorials
    • Python Keyword
    • Python Statement
    • Python Comment
    • Python Data Types
    • Python String Methods
    • Python Multiline Strings
    • Python Split Strings
    • Python Slice Strings
    • Iterate Strings in Python
    • Python String Format
    • Python String Concatenation
    • Python Permutations of a String
    • Python Numbers
    • Python List
    • Python List Reverse
    • Python List Slice
    • Python Nested List
    • Python Set
    • Python Tuple
    • Python Dictionary
    • Python Dict to JSON
    • Python Dictionary Examples
    • Python OrderedDict
    • Python Arrays
    • Python Generate SubArrays
    • Python Heapq (Heap queue)
    • Python Operators
    • Python XOR Operator
    • Operator Precedence
    • Python Namespace
    • Python For Loop
    • Python While Loop
    • Python If Else
    • Python Switch Case
    • Python Function
    • Higher Order Functions in Python
    • Python Class
    • Python Class Definition
    • Python Data Class
    • Python Inheritance
    • Python Multiple Inheritance
    • Python Static Method
    • File Handling in Python
    • Python Copy File
    • Python Exception Handling
    • Python Try Except
    • Python Lambda
    • Python Generator
    • Python Module
    Python Pandas in Action
    • Rename Columns using Pandas
    • Python Pandas to Read CSV Files
    • Python Pandas to Merge CSV Files
    • Python Dictionary to DataFrame
    • Python Find Length of List
    Python Important Functions
    • Python Glob()
    • Python Range()
    • Python Float Range()
    • Python Map()
    • Python Filter()
    • Python Enumerate()
    • Python Zip()
    • Python Join()
    • Python Ord()
    Python Advanced Tutorials
    • Python Multithreading
    • Python Socket Programming
    • Selenium Python
    • Python Unittest
    • Python Time Module
    • Python Datetime
    • Python IRC
    • PyLint in Python
    • Python Random Number
    • Python MongoDB
    • Python Pickle
    Python Code Examples
    • Python List Contains Elements
    • Python Search Dictionary by Value
    • Python Check Type of Variable
    • Python Check Version Using Code
    • Python Loop Through Files
    • Compare Strings in Python
    • Replace Strings in Python
    • Size of Integer in Python
    • Simple Socket in Python
    • Threaded Socket in Python
    Python Tips & Tricks
    • 30 Essential Python Tips
    • 10 Python Coding Tips
    • 12 Python Code Optimization Tips
    • 10 Python Programming Mistakes
    Python General Topics
    • Top 10 Python IDEs
    • Top 7 Python Interpreters
    • Top 7 Websites for Python
    • Top 5 Chrome Plugin for Python
    Python Quizzes - General
    • Python Quiz-1
    • Python Quiz-2
    • Python Quiz-3
    • Python Quiz-4
    Python Quizzes - Advanced
    • Python Quiz - Data Structures
    • Python Quiz - Threads
    • Python Quiz - DA
    Python MCQ - Strings
    • Python MCQ Strings-1
    • Python MCQ Strings-2
    Python MCQ - Classes `
    • Python MCQ Classes-1
    • Python MCQ Classes-2
    Python MCQ - Functions
    • Python MCQ Functions-1
    • Python MCQ Functions-2
    Python MCQ - File I/O
    • Python MCQ File I/O-1
    • Python MCQ File I/O-2
    Latest Posts
    • 30 Python Programming Questions On List, Tuple, and Dictionary
    • 4 Different Ways to Rename Columns in Pandas
    • 4 Unique Ways to Reverse a String in Python
    • 40 Google Interview Questions You Need to Join Google in 2023
    • 40 Python Exercises for Beginners
    • 44 Python Data Analyst Interview Questions
    • 7 Websites to Learn Python Programming

    Subscribe to Updates

    Get the latest tutorials from TechBeamers.

    Loading
    • About
    • Contact
    • Disclaimer
    • Privacy Policy
    • Terms of Use
    © 2023 TechBeamers. All Rights Reserved.

    Type above and press Enter to search. Press Esc to cancel.