🧑🏭 Functions¶
1. Definition and Calling a Function¶
In Python, a function is defined using the def
keyword. You can call a function by using its name followed by parentheses.
def greet():
print("Hello, world!")
# Call the function
greet() # prints: Hello, world!
Hello, world!
2. Parameters and Arguments¶
Information can be passed into functions as parameters. Parameters are specified after the function name, inside the parentheses.
def greet(name):
print(f"Hello, {name}!")
# Call the function with an argument
greet("Alice") # prints: Hello, Alice!
Hello, Alice!
3. Default Parameter Value¶
You can set a default value for parameters. If we call the function without an argument, it uses the default value.
def greet(name="world"):
print(f"Hello, {name}!")
greet("Alice") # prints: Hello, Alice!
greet() # prints: Hello, world!
Hello, Alice! Hello, world!
4. Return Values¶
A function can return a value using the return
statement.
def square(number):
return number ** 2
print(square(5)) # prints: 25
25
5. Arbitrary Arguments, *args¶
If you do not know how many arguments will be passed into your function, you can add a * before the parameter name.
def greet(*names):
for name in names:
print(f"Hello, {name}!")
greet("Alice", "Bob", "Charlie") # prints: Hello, Alice! Hello, Bob! Hello, Charlie!
Hello, Alice! Hello, Bob! Hello, Charlie!
6. Arbitrary Keyword Arguments, **kwargs¶
If you do not know how many keyword arguments will be passed into your function, add two asterisk: ** before the parameter name.
def person_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
person_info(name="Alice", age=25, city="New York")
name: Alice age: 25 city: New York
7. Lambda Functions¶
A lambda function is a small anonymous function. It can take any number of arguments, but can only have one expression.
square = lambda x: x ** 2
print(square(5)) # prints: 25
25
8. Type Hinting¶
Type hinting is a new feature since Python 3.5 that allows developers to indicate the type of a value within your Python code. This doesn't affect your code's runtime behavior, but it supports better IDE features and improves code readability.
Here's a function without type hints:
def greet(name):
return f"Hello, {name}"
And here it is with type hints:
def greet(name: str) -> str:
return f"Hello, {name}"
In the second function, name: str
indicates that name
should be a string, and -> str
indicates that the function will return a string.
You can also use complex type hints like List
, Dict
, Tuple
, etc.
from typing import List, Tuple
def info(names: List[str]) -> Tuple[str, int]:
return f"There are {len(names)} names.", len(names)
print(info(["Alice", "Bob"])) # prints: ('There are 2 names.', 2)
('There are 2 names.', 2)
Type Hinting in python 3.9 and above¶
Starting from Python 3.5, type hints were introduced, which provided a way to specify the expected type of variables, function parameters, and return values. This was largely facilitated by the typing
module. Here's an example with Python 3.8 and below:
from typing import List, Dict, Tuple, Optional
def process_data(data: List[int]) -> Tuple[Dict[str, int], Optional[str]]:
# some processing here
pass
In the function process_data
, the parameter data
is expected to be a list of integers, and the function is expected to return a tuple containing a dictionary and an optional string.
Starting with Python 3.9, the built-in collection types (list
, dict
, tuple
, set
) can be used as generic types, eliminating the need for equivalents from the typing
module (List
, Dict
, Tuple
, Set
). Here's the equivalent Python 3.9+ type hinting:
def process_data(data: list[int]) -> tuple[dict[str, int], Optional[str]]:
# some processing here
pass
As you can see, Python 3.9 allows for a more streamlined and natural syntax for type hinting. The |
operator can be used for specifying that a variable can be of either type, making it a neat replacement for typing.Optional
(which is essentially a shorthand for Union[..., None]
).
It's important to mention that while this change simplifies the syntax, Python's type hinting system remains optional and does not influence runtime behavior. It is primarily intended as an aid for static type checkers, linters, IDE features, and human readers of the code.
9. Docstrings¶
A docstring is a string literal that appears right after the definition of a function, method, class, or module, used to document the object. There are different styles of docstrings, one of which is the Google style that's widely used in scientific computing projects.
Here's an example:
def greet(name: str) -> str:
"""
Returns a greeting string.
Args:
name (str): The name to greet.
Returns:
str: A greeting string.
"""
return f"Hello, {name}"
This docstring provides a concise explanation of the function, along with its parameters and return values. It's enclosed in triple quotes, which allows for multi-line string literals in Python.
This approach is particularly useful in complex codebases, where it might be tricky to understand what a function does, what input it expects, and what it returns. By using type hinting and well-structured docstrings, you significantly improve code readability and maintainability.