Functions¶
Docstring 📝¶
Junior Coder Docstring Style
[cite_start]A simple, descriptive docstring[cite: 147]. Note that the is_even
function must be defined with this docstring for the subsequent __doc__
example to work correctly.
Output | |
---|---|
Senior Coder Docstring Style (Using Type Hinting and Standard Format)
[cite_start]A more structured docstring using type hints (num: int -> str
) and a formal format (like NumPy or Google style), listing arguments and return values[cite: 147].
Output | |
---|---|
Calling the Function
Assuming the function definition from the first example is active in the environment.
Reading Docstrings (.__doc__
)¶
Custom Docstring
[cite_start]Access the docstring using the special .__doc__
attribute[cite: 147].
Docstring of Built-in print()
Built-in functions and objects also have docstrings.
Output | |
---|---|
Docstring of Built-in type()
Two Points of View: Responsibility¶
View
Whenever you design a function, it is your responsibility to ensure that your code executes without any errors.
- Junior Coder: Focuses on writing the logic to pass the test cases.
- Senior Coder: Writes robust functions that include type checking (like in the first
is_even
example) and clear documentation (docstrings) to prevent misuse and runtime errors, reflecting code quality and reliability.
Parameter vs Arguments 🤝¶
Definitions
- Parameters are the names defined in the function signature (during function creation time).
- Arguments are the actual values passed to the function when it is called (during function use time).
Output | |
---|---|
Default Argument¶
Default Argument
Parameters can be assigned a default value in the function definition. If no argument is provided for that parameter during the call, the default value is used.
Output | |
---|---|
Positional Argument¶
Positional Argument
Arguments passed in the function call are mapped to parameters based on their position or order.
Output | |
---|---|
Keyword Argument¶
Keyword Argument
Arguments are passed by explicitly naming the parameter they should correspond to. This allows the arguments to be specified in any order.
Output | |
---|---|
*args
& **kwargs
📦¶
The special Python keywords *args
and **kwargs
are used to pass a variable length of arguments to a function.
Variable Positional Arguments (*args
)
The *args
syntax allows you to pass a variable number of non-keyword arguments (positional arguments) to a function. Inside the function, args
(or whatever name you choose) is treated as a tuple containing all the passed non-keyword arguments.
Output | |
---|---|
Variable Keyword Arguments (**kwargs
)
The **kwargs
syntax allows you to pass any number of keyword arguments (key-value pairs) to a function. Inside the function, kwargs
(or whatever name you choose) is treated as a dictionary containing all the passed keyword arguments.
Output | |
---|---|
Important Points to Remember
-
Order Matters: If you use a combination of argument types, the order in the function signature must be: $$ \text{normal arguments} \rightarrow \text{positional args } (\text{args}) \rightarrow \text{keyword args } (*\text{kwargs}) $$
-
Naming Convention: The words "args" and "kwargs" are just a convention (standard practice). You can use any valid variable names (e.g.,
*elements
,**attributes
), but stick to the convention for better readability.
Functions Without a return
Statement 🔄¶
Implicit Return Value: None
If a function or method executes without an explicit return
statement, it implicitly returns the value None
. Many list methods, like .append()
, modify the list in place and return None
.
Variable Scope 🌐¶
- In Python, variables are resolved based on the LEGB rule (Local, Enclosing, Global, Built-in).
Global vs. Local Variables
A function can access (read) a variable defined in the Global scope if no local variable with the same name exists.
When a variable is assigned a value inside a function, it becomes a Local variable, which takes precedence over the global variable with the same name. It does not affect the global variable.
When an immutable argument (x=3
) is passed to a function, the function receives a copy of the reference (pass-by-object-reference). Operations that modify the variable (like x = x + 1
) create a new local variable x
inside the function's scope, leaving the global x
untouched.
The global
keyword declares that a variable inside the function should refer to the global one. You cannot use global
on a variable that is already defined as a function parameter, as parameters are always local to the function.
Nested Functions 🪜¶
Nested Function Execution
A function defined inside another function (a nested function) can only be called from within its enclosing function.
Output | |
---|---|
Calling the outer function executes it, which in turn calls the inner function.
A variable assignment (x = 'abc'
) inside the inner function (h
) creates a local variable x
within h
. This new x
does not affect the x
in the enclosing function (g
).
Output | |
---|---|
When the inner function (h
) also takes a parameter named x
, it has its own separate local scope. Modifications to x
inside h
do not affect the x
in the enclosing function (g
) or the global x
.
Functions as First-Class Citizens 🥇¶
In Python, functions are considered first-class citizens, meaning they possess the following properties, similar to data types like integers or strings:
- Functions are a data type (
<class 'function'>
). - They can be assigned to variables.
- They can be stored in data structures (lists, tuples, sets, dictionaries).
- They can be passed as arguments to other functions.
- They can be returned as values from other functions.
Properties of Functions as Data
A function is a distinct type, and like any object, it has a unique memory address (id
).
The function object can be assigned to a new variable (x
). Both names point to the same object (same ID).
You can delete the original name, but the function object remains if it is referenced by another name (like x
in the previous step). The function must be redefined to use the original name again.
Output | |
---|---|
Output | |
---|---|
Function objects can be stored inside lists, tuples, sets, or dictionaries.
Output | |
---|---|
Functions are considered immutable/hashable, allowing them to be stored in sets.
Output | |
---|---|
A function (f
) can define and return another function (x
), which can then be called immediately.
Output | |
---|---|
A function (func_c
) can accept another function (func_a
) as an argument and execute it.