YouTip LogoYouTip

Python Functions

## Introduction to Python Functions In Python, a **function** is a structured, reusable block of code designed to perform a single, focused, or related action. Functions are fundamental to writing clean, maintainable code. They improve your application's modularity and enable high levels of code reuse. While Python comes with many built-in functions (such as `print()`, `len()`, and `range()`), you can also define your own functions. These are referred to as **user-defined functions**. --- ## Defining a Function You can define custom functions to implement any logic you require. When defining a function in Python, keep the following rules in mind: * **The `def` Keyword:** Every function definition begins with the `def` keyword, followed by the function name and parentheses `()`. * **Parameters:** Any input parameters or arguments must be placed within these parentheses. You can also define default values for these parameters inside the parentheses. * **Docstrings:** The first statement of a function body can optionally be a string literal. This is the function's documentation string (docstring), used to describe what the function does. * **Colon and Indentation:** The function block starts after a colon (`:`) and must be indented. * **The `return` Statement:** The `return ` statement exits a function, optionally passing back an expression to the caller. A `return` statement with no arguments (or omitting the `return` statement entirely) implicitly returns `None`. ### Syntax ```python def function_name(parameters): """Optional function docstring.""" function_suite return ``` By default, arguments are matched to parameters sequentially based on the order in which they are declared. ### Basic Example The following is a simple Python function. It takes a string as an input parameter and prints it to the standard output: ```python def print_me(input_string): """Prints the passed string to the standard output.""" print(input_string) return ``` --- ## Calling a Function Defining a function only specifies its name, parameters, and internal code block structure. To execute the code inside the function, you must **call** it from another block of code or directly from the Python interpreter. The following example demonstrates how to call the `print_me()` function: ```python # Function definition def print_me(input_string): """Prints any passed string.""" print(input_string) return # Calling the function print_me("Calling the user-defined function for the first time!") print_me("Calling the same function again.") ``` ### Output ```text Calling the user-defined function for the first time! Calling the same function again. ``` --- ## Parameter Passing: Mutable vs. Immutable Objects In Python, types are associated with **objects**, not variables. A variable is simply a reference (or pointer) to an object in memory. For example: ```python a = [1, 2, 3] a = "YouTip" ``` In this snippet, `[1, 2, 3]` is a `list` object, and `"YouTip"` is a `string` object. The variable `a` has no fixed type; it is merely a reference that first points to a list object and is later reassigned to point to a string object. ### Mutable vs. Immutable Objects Python handles data types based on whether they are mutable (changeable) or immutable (unchangeable): * **Immutable Types:** Objects of types like integers, floats, strings, and tuples cannot be modified after they are created. If you assign `a = 5` and then `a = 10`, you are not changing the value of the original integer object `5`. Instead, you are creating a new integer object `10` and pointing `a` to it. * **Mutable Types:** Objects of types like lists, dictionaries, and sets can be modified in place. If you assign `la = [1, 2, 3, 4]` and then modify an element with `la = 5`, the list object itself is modified. Its memory address remains the same. ### How Arguments are Passed to Functions Because everything in Python is an object, argument passing is best understood through the lens of object mutability rather than traditional "pass-by-value" or "pass-by-reference" terminology: * **Passing Immutable Objects:** Similar to pass-by-value. When you pass integers, strings, or tuples to a function, modifying the parameter inside the function does not affect the original object outside the function. Instead, the local variable is reassigned to a new object. * **Passing Mutable Objects:** Similar to pass-by-reference. When you pass lists, dictionaries, or sets to a function, any in-place modifications made to the parameter inside the function will reflect on the original object outside the function. #### Example: Passing an Immutable Object (Integer) ```python def change_int(num): num = 10 # Reassigns local variable 'num' to a new integer object val = 2 change_int(val) print(val) # Output is still 2 ``` **Explanation:** The variable `val` points to the integer object `2`. When passed to `change_int()`, the local variable `num` also points to `2`. When `num = 10` is executed, a new integer object `10` is created, and `num` is reassigned to point to it. The original variable `val` still points to `2`. #### Example: Passing a Mutable Object (List) ```python def modify_list(my_list): """Appends a list to the passed list.""" my_list.append([1, 2, 3, 4]) print("Inside the function:", my_list) return # Calling the function sample_list = [10, 20, 30] modify_list(sample_list) print("Outside the function:", sample_list) ``` ### Output ```text Inside the function: [10, 20, 30, [1, 2, 3, 4]] Outside the function: [10, 20, 30, [1, 2, 3, 4]] ``` --- ## Function Arguments When calling a function, you can pass arguments using four different mechanisms: 1. Required arguments (Positional arguments) 2. Keyword arguments 3. Default arguments 4. Variable-length arguments (`*args` and `**kwargs`) ### 1. Required Arguments Required arguments must be passed to the function in the correct positional order. The number of arguments in the function call must match the number of parameters defined in the function signature. If you call a function without its required arguments, Python will raise a `TypeError`: ```python def print_me(input_string): """Prints the passed string.""" print(input_string) return # Calling the function without arguments raises an error print_me() ``` ### Output ```text Traceback (most recent call last): File "test.py", line 7, in print_me() TypeError: print_me() missing 1 required positional argument: 'input_string' ``` ### 2. Keyword Arguments Keyword arguments allow you to pass arguments to a function using the parameter names as identifiers (`parameter_name = value`). Using keyword arguments allows you to pass arguments in any order, as the Python interpreter uses the names to match values to parameters. ```python def print_info(name, age): """Prints the passed user information.""" print("Name:", name) print("Age:", age) return # Calling print_info with keyword arguments in a different order print_info(age=50, name="Miki") ``` ### Output ```text Name: Miki Age: 50 ``` ### 3. Default Arguments A default argument is an argument that assumes a default value if a value is not provided in the function call. You can define default values in the function signature using the assignment operator (`=`). ```python def print_info(name, age=35): """Prints user information. Defaults age to 35 if not provided.""" print("Name:", name) print("Age:", age) return # Call with both arguments print_info(age=50, name="Miki") # Call with only the required argument print_info(name="Miki") ``` ### Output ```text Name: Miki Age: 50 Name: Miki Age: 35 ``` ### 4. Variable-Length Arguments Sometimes you need to process a function with more arguments than you specified when defining the function. These are called variable-length arguments. #### Positional Variable-Length Arguments (`*args`) An asterisk (`*`) before a variable name in the function definition holds all non-keyword variable arguments as a **tuple**. ```python def print_non_keyword_args(first_arg, *var_args): """Prints variable positional arguments.""" print("First argument:", first_arg) print("Variable arguments:") for arg in var_args: print(arg) return # Call with multiple arguments print_non_keyword_args(10) print_non_keyword_args(70, 60, 50, 40) ``` ### Output ```text First argument: 10 Variable arguments: First argument: 70 Variable arguments: 60 50 40 ``` #### Keyword Variable-Length Arguments (`**kwargs`) Two asterisks (`**`) before a variable name allow you to pass a variable number of keyword arguments. Inside the function, these arguments are received as a **dictionary**. ```python def print_keyword_args(first_arg, **var_kwargs): """Prints variable keyword arguments.""" print("First argument:", first_arg) print("Variable keyword arguments:", var_kwargs) return # Call with keyword arguments print_keyword_args(100, user="Alice", role="Admin") ``` ### Output ```text First argument: 100 Variable keyword arguments: {'user': 'Alice', 'role': 'Admin'} ``` --- ## Best Practices and Considerations * **Keep Functions Focused:** A function should adhere to the Single Responsibility Principle (SRP). It should do one thing and do it well. * **Use Clear Naming Conventions:** Use lowercase words separated by underscores (`snake_case`) for function names to comply with PEP 8 guidelines. * **Avoid Mutable Default Arguments:** Never use mutable objects (like empty lists `[]` or dictionaries `{}`) as default arguments. Because default arguments are evaluated once when the function is defined, subsequent calls will share the same mutable object, leading to unexpected side effects. *Incorrect:* ```python def append_to(element, target_list=[]): target_list.append(element) return target_list ``` *Correct:* ```python def append_to(element, target_list=None): if target_list is None: target_list = [] target_list.append(element) return target_list ```
← Att Ios Ui LabelHttp Status Codes β†’