Python 函数
Python 函数
Section titled “Python 函数”函数是旨在执行特定任务的可重用代码的命名块。函数有助于组织代码、使应用程序更模块化、提高可读性并促进代码重用。
Python 提供了许多内置函数(例如 print()、len()、type())。您也可以定义自己的函数,称为用户自定义函数。
函数使用 def 关键字定义,后跟函数名称、括号 () 和冒号 :。函数内的代码块必须缩进。
- 语法以
def function_name(parameters):开头。 - 参数(函数的输入)列在括号内,用逗号分隔。函数可以有零个或多个参数。
- 第一个语句 可以 是一个可选的文档字符串(docstring),用三重引号(
"""这里是文档字符串""")括起来,解释函数的功能。强烈建议这样做。 - 冒号后的缩进代码块是函数体(suite)。
return语句退出函数并可选地将一个值发送回调用者。如果省略return或不带表达式使用,函数将隐式返回None。
def function_name(parameter1, parameter2=default_value): """可选的文档字符串,解释函数功能。""" # 函数体(缩进代码) result = parameter1 + parameter2 return result # 可选的 return 语句一个接受名字并打印问候语的简单函数:
def greet(name): """打印一个简单的问候语给定的名字。""" print(f"Hello, {name}!") # 隐式返回 None定义函数并不会执行它。要运行函数内的代码,您必须 调用 它,方法是使用函数名称后跟括号,并提供任何必需的参数。
# 首先定义函数def greet(name): """打印一个简单的问候语。""" print(f"Hello, {name}!")
# 现在调用函数greet("Alice")greet("Bob")输出:
Hello, Alice!Hello, Bob!参数传递(按对象引用传递)
Section titled “参数传递(按对象引用传递)”在 Python 中,参数传递使用一种有时被称为“按对象引用传递”或“按赋值传递”的机制。其含义如下:
示例(可变对象):
def modify_list(my_list): """向传递的列表中添加一个项。""" my_list.append(100) # 修改原始列表对象 print(f"函数内部: {my_list}")
numbers = [10, 20, 30]modify_list(numbers)print(f"函数外部: {numbers}") # 修改保留输出:
Inside function: [10, 20, 30, 100]Outside function: [10, 20, 30, 100]示例(重新赋值):
def reassign_list(my_list): """将参数重新赋值给一个新列表。""" my_list = [1, 2, 3, 4] # 参数现在指向一个 *新* 列表 print(f"函数内部 (重新赋值后): {my_list}")
numbers = [10, 20, 30]reassign_list(numbers)print(f"函数外部: {numbers}") # 原始列表不受影响输出:
Inside function (after reassign): [1, 2, 3, 4]Outside function: [10, 20, 30]函数参数类型
Section titled “函数参数类型”Python 提供了灵活的方式来定义和调用具有不同参数类型的函数:
1. 位置参数
Section titled “1. 位置参数”这些是标准参数,根据其顺序进行匹配。调用时提供的参数数量必须与定义的参数数量一致。
def describe_pet(animal_type, pet_name): print(f"I have a {animal_type} named {pet_name}.")
describe_pet("hamster", "Harry") # 正确的顺序# describe_pet("Fluffy") # TypeError: 缺少1个必需的位置参数: 'pet_name'2. 关键字参数
Section titled “2. 关键字参数”您可以在函数调用中通过参数名称来指定参数。这允许您不按顺序传递参数,并提高了代码的清晰度。
def describe_pet(animal_type, pet_name): print(f"I have a {animal_type} named {pet_name}.")
describe_pet(pet_name="Willie", animal_type="dog") # 顺序无关紧要describe_pet(animal_type="cat", pet_name="Whiskers")3. 默认参数值
Section titled “3. 默认参数值”您可以在函数定义中为参数提供默认值。如果在调用中没有为该参数提供参数,则使用默认值。带有默认值的参数必须位于没有默认值的参数 之后。
def describe_pet(pet_name, animal_type="dog"): # animal_type 的默认值 print(f"I have a {animal_type} named {pet_name}.")
describe_pet(pet_name="Buddy") # 使用默认的 animal_type 'dog'describe_pet(pet_name="Lucy", animal_type="cat") # 覆盖默认值输出:
I have a dog named Buddy.I have a cat named Lucy.4. 可变长度参数 (*args)
Section titled “4. 可变长度参数 (*args)”要让函数接受任意数量的 位置 参数,可以在参数名称前使用星号 *(通常约定为 *args)。这将把任何额外的按位置传递的参数收集到一个元组 (tuple) 中。
def make_pizza(size, *toppings): """打印正在订购的比萨及其配料。""" print(f"\nMaking a {size}-inch pizza with the following toppings:") if toppings: for topping in toppings: print(f"- {topping}") else: print("- Plain")
make_pizza(12, "mushrooms")make_pizza(16, "pepperoni", "green peppers", "extra cheese")make_pizza(10) # 没有额外的按位置传递的参数,toppings 是一个空元组输出:
Making a 12-inch pizza with the following toppings:- mushrooms
Making a 16-inch pizza with the following toppings:- pepperoni- green peppers- extra cheese
Making a 10-inch pizza with the following toppings:- Plain5. 可变长度关键字参数 (**kwargs)
Section titled “5. 可变长度关键字参数 (**kwargs)”要让函数接受任意数量的 关键字 参数,可以在参数名称前使用两个星号 **(通常约定为 **kwargs)。这将把任何额外的按关键字传递的参数收集到一个字典 (dictionary) 中。
def build_profile(first, last, **user_info): """构建一个包含用户信息的字典。""" profile = {'first_name': first, 'last_name': last} profile.update(user_info) # 添加任何额外的关键字参数 return profile
user1 = build_profile('albert', 'einstein', location='princeton', field='physics')user2 = build_profile('marie', 'curie', field='chemistry', awards=2)
print(user1)print(user2)输出:
{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}{'first_name': 'marie', 'last_name': 'curie', 'field': 'chemistry', 'awards': 2}6. 仅限关键字参数 (Python 3)
Section titled “6. 仅限关键字参数 (Python 3)”放在 *args 或裸露的 * 之后 的参数必须使用关键字指定。
def process_data(*, input_file, output_file, force=False): """要求 input_file 和 output_file 必须通过关键字传递。""" print(f"Processing {input_file} to {output_file}. Force={force}")
# process_data("in.txt", "out.txt") # TypeError!process_data(input_file="in.csv", output_file="out.csv")process_data(input_file="data.zip", output_file="proc.zip", force=True)7. 仅限位置参数 (Python 3.8+)
Section titled “7. 仅限位置参数 (Python 3.8+)”放在裸露的 / 之前 的参数只能通过位置指定,不能使用关键字。
def example_pos_only(a, b, / , c, d): """a 和 b 是仅限位置参数。""" print(f"a={a}, b={b}, c={c}, d={d}")
example_pos_only(1, 2, c=3, d=4) # 工作正常# example_pos_only(a=1, b=2, c=3, d=4) # TypeError!a 和 b 是仅限位置参数Lambda(匿名)函数
Section titled “Lambda(匿名)函数”Lambda 函数提供了一种创建小型匿名函数(没有名称的函数)的简写语法。它们使用 lambda 关键字定义。
- 语法:
lambda arguments: expression - 可以接受任意数量的参数,但只能有一个表达式。
- 当 lambda 被调用时,表达式会被评估并返回。
- 通常用于需要简单函数对象的地方(例如,作为
map()、filter()、sorted()的参数)。
示例:
# 等同于: def add(x, y): return x + yadder = lambda x, y: x + y
print(f"总值: {adder(10, 20)}")print(f"总值: {adder(5, -2)}")
# 将 lambda 与 sorted() 一起使用points = [(1, 2), (3, 1), (5, -4), (2, 3)]# 根据第二个元素 (y 坐标) 对点进行排序points_sorted_by_y = sorted(points, key=lambda point: point[1])print(f"按 y 排序: {points_sorted_by_y}")输出:
Value of total: 30Value of total: 3Sorted by y: [(5, -4), (3, 1), (1, 2), (2, 3)]return 语句
Section titled “return 语句”return 语句用于退出函数并将一个值返回到函数被调用的位置。函数可以返回任何类型的对象。
def subtract(arg1, arg2): """从 arg1 中减去 arg2 并返回结果。""" total = arg1 - arg2 print(f"函数内部,结果: {total}") return total
# 调用函数并存储返回值result_value = subtract(20, 5)print(f"函数外部,结果: {result_value}")
# 可以返回多个值(作为元组)def get_coordinates(): return 10, 20 # 自动打包成一个元组
x, y = get_coordinates() # 解包返回的元组print(f"坐标: x={x}, y={y}")输出:
Inside the function, result: 15Outside the function, result: 15Coordinates: x=10, y=20变量作用域(LEGB 规则)
Section titled “变量作用域(LEGB 规则)”变量的作用域决定了程序中可以在哪里访问它。
Python 按照 LEGB 顺序搜索变量名。
total = 0 # 全局变量
def sum_and_update(arg1, arg2): # 除非声明为 global,否则这里的 'total' 指的是一个 *新的* 局部变量 # global total # 取消此行注释以修改全局 'total' total = arg1 + arg2 # 创建一个局部 'total',遮蔽了全局变量 print(f"函数内部局部 total: {total}") return total
sum_and_update(10, 20)print(f"函数外部全局 total: {total}") # 全局 'total' 保持不变输出(未取消注释 global total):
Inside function local total: 30Outside function global total: 0类型提示 (PEP 484)
Section titled “类型提示 (PEP 484)”现代 Python (3.5+) 支持可选的类型提示,允许您使用预期的类型来标注函数的参数和返回值。类型提示不影响运行时行为,但对于静态分析工具(如 MyPy)、IDE 和提高代码清晰度非常有价值。
import math
def calculate_circumference(radius: float) -> float: """根据半径计算圆的周长。""" if radius < 0: raise ValueError("半径不能为负数") return 2 * math.pi * radius
# 类型提示有助于在静态分析时捕获潜在错误circum = calculate_circumference(10.5)print(f"周长: {circum:.2f}")
# 如果运行 Mypy,此调用会被标记:# result_wrong_type = calculate_circumference("hello")常见的类型从 typing 模块导入(例如 List、Dict、Tuple、Optional)。