Consider creating a function to calculate the area of a trapezoid, then use it to determine the area of a trapezoid with an upper base of 4cm, lower base of 3cm, and height of 5cm. However, swapping the positions of the height and lower base parameters would yield incorrect results:
def area(upper_base, lower_base, height):
return (upper_base + lower_base) * height / 2
print("Correct result:", area(4, 3, 5))
print("Incorrect result:", area(4, 5, 3))
The output will be:
Correct result: 17.5
Incorrect result: 13.5
Thus, parameter ordering is crucial when calling functions to avoid such errors that might be difficult to spot.
Keyword Arguments in Python Functions
Until now, we've used positional arguments where actual parameters must correspond exactly to formal parameters in number and order. This section introduces keyword arguments which allow more flexible parameter passing.
Keyword arguments specify parameter values by their names rather than their positions. When using this approach, the order of parameters doesn't matter as long as the names match correctly.
Therefore, function parameter names should be semantically meaningful to clearly indicate what each passed parameter represents.
Here's an example using keyword arguments:
def display_strings(str1, str2):
print("str1:", str1)
print("str2:", str2)
# Using positional arguments
display_strings("http://c.biancheng.net/python/", "http://c.biancheng.net/shell/")
# Using keyword arguments
display_strings("http://c.biancheng.net/python/", str2="http://c.biancheng.net/shell/")
display_strings(str2="http://c.biancheng.net/python/", str1="http://c.biancheng.net/shell/")
The execution results show:
str1: http://c.biancheng.net/python/
str2: http://c.biancheng.net/shell/
str1: http://c.biancheng.net/python/
str2: http://c.biancheng.net/shell/
str1: http://c.biancheng.net/shell/
str2: http://c.biancheng.net/python/
It's evident that both positional and keyword arguments can be used when calling parameterized functions. In keyword argument usage, parameter order is arbitrary. Mixed usage is also allowed, but all keyword arguments must follow all positional arguments. For example, the following code is invalid:
# Positional arguments must precede keyword arguments
display_strings(str1="http://c.biancheng.net/python/", "http://c.biancheng.net/shell/")
Python will throw a syntax error:
SyntaxError: positional argument follows keyword argument
Default Parameters in Python Functions
When calling a function without specifying certain parameters, Python raises an exception. To address this, Python allows setting default values for parameters during function definition. If a parameter has a default value and isn't explicitly provided during the call, it uses its default value.
The syntax for defining a function with default parameters is:
def function_name(..., parameter_name, parameter_name=default_value):
# body
Note that parameters with defaults must come after those without defaults to prevent syntax errors.
The following example demonstrates defining and calling functions with default parameters:
# str1 has no default, str2 does
def display_strings(str1, str2="http://c.biancheng.net/python/"):
print("str1:", str1)
print("str2:", str2)
display_strings("http://c.biancheng.net/shell/")
display_strings("http://c.biancheng.net/java/", "http://c.biancheng.net/golang/")
Output:
str1: http://c.biancheng.net/shell/
str2: http://c.biancheng.net/python/
str1: http://c.biancheng.net/java/
str2: http://c.biancheng.net/golang/
In this case, the second parameter has a default value. When calling the function with just one argument, it assigns to str1, while str2 takes its default value. Alternatively, both arguments can be specified, overriding the default value of str2.
Combining with keyword arguments, the following calls are valid:
display_strings(str1="http://c.biancheng.net/shell/")
display_strings("http://c.biancheng.net/java/", str2="http://c.biancheng.net/golang/")
display_strings(str1="http://c.biancheng.net/java/", str2="http://c.biancheng.net/golang/")
Remember, default parameters must appear after non-default ones. The following definition is incorrect:
# Syntax error
def display_strings(str1="http://c.biancheng.net/python/", str2, str3):
pass
Here, str1 has a default value, while str2 and str3 do not, so str1 must be placed after them.
To check default values of parameters in built-in or third-party functions, use the __defaults__ attribute:
print(display_strings.__defaults__)
This outputs:
('http://c.biancheng.net/python/',)
Variable Arguments (*args, **kwargs)
Python supports variable-length arguments allowing functions to accept any number of parameters. These are known as variable arguments or indefinite arguments.
1) Variable Arguments with *
The syntax is:
*args
This creates an empty tuple named args that accepts any number of non-keyword arguments.
An example:
# Function accepting variable arguments
def display_strings(home, *strings):
print(home)
print("strings =", strings)
for s in strings:
print(s)
# Passing any number of arguments
display_strings("http://c.biancheng.net",
"http://c.biancheng.net/python/",
"http://c.biancheng.net/shell/")
Output:
http://c.biancheng.net
strings = ('http://c.biancheng.net/python/', 'http://c.biancheng.net/shell/')
http://c.biancheng.net/python/
http://c.biancheng.net/shell/
Here, the last parameter collects all extra non-keyword arguments into the strings tuple.
Variable arguments don't have to be at the end. Consider modifying the function:
# Function accepting variable arguments
def display_strings(*strings, home):
print(home)
print("strings =", strings)
for s in strings:
print(s)
display_strings("http://c.biancheng.net",
"http://c.biancheng.net/python/",
home="http://c.biancheng.net/shell/")
In this case, strings is the first parameter. However, when calling the function, the regular parameter must be passed as a keyword argument, otherwise all arguments are assigned to strings.
2) Variable Arguments with **
The syntax is:
**kwargs
This creates a dictionary named kwargs that receives any number of keyword arguments.
Example:
# Function accepting variable arguments
def display_strings(home, *strings, **courses):
print(home)
print(strings)
print(courses)
# Calling function
display_strings("C语言中文网",
"http://c.biancheng.net",
"http://c.biancheng.net/python/",
shell_course="http://c.biancheng.net/shell/",
go_course="http://c.biancheng.net/golang/",
java_course="http://c.biancheng.net/java/")
Output:
C语言中文网
('http://c.biancheng.net', 'http://c.biancheng.net/python/')
{'shell_course': 'http://c.biancheng.net/shell/', 'go_course': 'http://c.biancheng.net/golang/', 'java_course': 'http://c.biancheng.net/java/'}
Here, the first argument goes to home, the next two non-keyword arguments to strings, and the last three keyword arguments to courses.
By default, *args is an empty tuple, and **kwargs is an empty dictionary. Functions with these arguments can be called without providing values.
Reverse Parameter Collection
Python allows unpacking lists, tuples, and dictionaries directly into function arguments. When passing a list or tuple, prefix with *, and when passing a dictionary, prefix with **.
Example:
def display_strings(name, address):
print("name:", name)
print("address:", address)
data = ["Python tutorial", "http://c.biancheng.net/python/"]
# Using reverse parameter collection
display_strings(*data)
Output:
name: Python tutorial
address: http://c.biancheng.net/python/
Another example with a dictionary:
def display_strings(name, address):
print("name:", name)
print("address:", address)
data = {'name': "Python tutorial", 'address': "http://c.biancheng.net/python/"}
# Using reverse parameter collection
display_strings(**data)
Output:
name: Python tutorial
address: http://c.biancheng.net/python/
Reverse parameter collection works with functions that have variable arguments:
def display_strings(name, *addresses):
print("name:", name)
print("addresses:", addresses)
data = ["http://c.biancheng.net/python/",
"http://c.biancheng.net/shell/",
"http://c.biancheng.net/golang/"]
# Using reverse parameter collection
display_strings("Python tutorial", *data)
Output:
name: Python tutorial
addresses: ('http://c.biancheng.net/python/', 'http://c.biancheng.net/shell/', 'http://c.biancheng.net/golang/')
If not prefixed with *, Python treats the entire list as a single argument:
def display_strings(name, *addresses):
print("name:", name)
print("addresses:", addresses)
data = ["Python tutorial",
"http://c.biancheng.net/python/",
"http://c.biancheng.net/shell/",
"http://c.biancheng.net/golang/"]
display_strings(data) # Passes the whole list as one argument
Output:
name: ['Python tutorial', 'http://c.biancheng.net/python/', 'http://c.biancheng.net/shell/', 'http://c.biancheng.net/golang/']
addresses: ()
Python None Type
None is a special constant in Python representing the absence of a value. Unlike False, it does not represent zero or an empty string. It belongs to the NoneType class.
None is distinct from empty containers like [] and "":
None is [] # False
None is "" # False
type(None) # <class>
</class>
None is used in assertions, conditional checks, and when functions don't return anything. For instance, print() returns None:
spam = print('Hello!')
# Hello!
None == spam # True
All functions without explicit return statements implicitly return None.
Return Statement in Functions
Functions can return values using the return statement. A function may contain multiple return statements, but only one executes per function call.
Syntax:
return [value]
Example:
def add(a, b):
c = a + b
return c
# Assigning function result to variable
result = add(3, 4)
print(result) # 7
# Using function result as argument
print(add(3, 4)) # 7
Functions can also return boolean values:
def is_greater_zero(x):
if x > 0:
return True
else:
return False
print(is_greater_zero(5)) # True
print(is_greater_zero(0)) # False
Returning Multiple Values
While a function typically returns one value, it can effectively return multiple values through sequences like lists or tuples.
Two approaches:
- Create a list or tuple containing values to return
- Return multiple values separated by commas; Python wraps them in a tuple
Example:
def return_list():
urls = [
"http://c.biancheng.net/python/",
"http://c.biancheng.net/shell/",
"http://c.biancheng.net/golang/"
]
return urls
def return_tuple():
return (
"http://c.biancheng.net/python/",
"http://c.biancheng.net/golang/",
"http://c.biancheng.net/golang/"
)
print("return_list =", return_list())
print("return_tuple =", return_tuple())
Output:
return_list = ['http://c.biancheng.net/python/', 'http://c.biancheng.net/shell/', 'http://c.biancheng.net/golang/']
return_tuple = ('http://c.biancheng.net/python/', 'http://c.biancheng.net/golang/', 'http://c.biancheng.net/golang/')
Use sequence unpacking to receive multiple values:
def return_list():
urls = [
"http://c.biancheng.net/python/",
"http://c.biancheng.net/shell/",
"http://c.biancheng.net/golang/"
]
return urls
python_url, shell_url, golang_url = return_list()
print("python_url =", python_url)
print("shell_url =", shell_url)
print("golang_url =", golang_url)
Output:
python_url = http://c.biancheng.net/python/
shell_url = http://c.biancheng.net/shell/
golang_url = http://c.biancheng.net/golang/
Recursive Functions
A recursive function calls itself within its body. Each call enters a new layer until the innermost completes, then unwinds.
Example: Given a sequence where f(0)=1, f(1)=4, f(n+2)=2*f(n+1)+f(n), find f(10).
def fn(n):
if n == 0:
return 1
elif n == 1:
return 4
else:
return 2 * fn(n - 1) + fn(n - 2)
print("fn(10) result:", fn(10))
The recursion ends when it reaches base cases (n=0 or n=1). Recursive functions must progress toward known values to avoid infinite recursion.
Variable Scope (Local vs Global)
Variable scope defines where a variable can be accessed. Variables defined inside a function are local, while those outside are global.
Local Variables
Variables defined within a function exist only within that scope:
def demo():
address = "http://c.biancheng.net/python/"
print("Inside function:", address)
demo()
print("Outside function:", address) # Error: NameError
Function parameters are also local variables.
Global Variables
Variables defined outside all functions are global and accessible throughout the program:
address = "http://c.biancheng.net/shell/"
def text():
print("Inside function:", address)
text()
print("Outside function:", address)
To modify a global variable inside a function, use the global keyword:
def text():
global address
address = "http://c.biancheng.net/java/"
print("Inside function:", address)
text()
print("Outside function:", address)
Accessing Variables by Scope
Python provides functions to access variables by scope:
globals(): Returns a dictionary of all global variableslocals(): Returns a dictionary of all variables in current scopevars(object): Returns a dictionary of variables in a specified object's scope
Using Global Variables with Same Names
If a local variable shares the same name as a global one, the local version shadows the global:
name = "Python tutorial"
def demo():
print(name) # Accesses global variable
name = "Shell tutorial" # Creates local variable
demo() # Error: UnboundLocalError
To access or modify the global variable:
- Use
globals():
name = "Python tutorial"
def demo():
print(globals()['name']) # Access global
globals()['name'] = "Java tutorial"
name = "Shell tutorial" # Local variable
demo()
print(name)
- Use the
globalkeyword:
name = "Python tutorial"
def demo():
global name
print(name) # Access global
name = "Shell tutorial" # Modify global
demo()
print(name)
Nested Functions and the nonlocal Keyword
Functions can be defined inside other functions. Nested functions can only be accessed within their parent function unless returned.
def outer_function():
def inner_function():
print("http://c.biancheng.net/python/")
inner_function()
outer_function()
To extend the scope of a nested function:
def outer_function():
def inner_function():
print("Calling inner function")
return inner_function
new_inner = outer_function()
new_inner() # Works
If a nested function defines a variable with the same name as an outer function's variable, it shadows it:
def outer_function():
name = "Variable defined in outer function"
def inner_function():
print(name)
name = "Variable defined in inner function" # Error: UnboundLocalError
inner_function()
outer_function()
Use the nonlocal keyword to access the outer variable:
def outer_function():
name = "Variable defined in outer function"
def inner_function():
nonlocal name
print(name)
name = "Variable defined in inner function"
inner_function()
outer_function()
Lambda Expressions (Anonymous Functions)
For simple functions with a single expression, Python offers lambda expressions:
name = lambda [parameters] : expression
Equivalent to:
def name(parameters):
return expression
Example:
add = lambda x, y: x + y
print(add(3, 4)) # 7
Lambda expressions provide concise syntax for one-line functions, improving code readability and performance for temporary use.
Functional Programming with map(), filter(), and reduce()
Functional programming emphasizes pure functions and immutability. Python supports functional programming through map(), filter(), and reduce().
map() Function
Applies a function to each element of an iterable:
numbers = [1, 2, 3, 4, 5]
doubled = map(lambda x: x * 2, numbers)
print(list(doubled)) # [2, 4, 6, 8, 10]
filter() Function
Returns elements for which a predicate function evaluates to True:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # [2, 4, 6, 8, 10]
reduce() Function
Applies a binary function cumulatively to the items of an iterable:
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120