Files
2026-05-06 11:21:42 +08:00

534 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 函数
# 语法
# def function_name(parameters):
# """文档字符串(可选)"""
# # 函数体
# return value # 可选
# 组成部分:
# 函数名:标识函数的名称,遵循变量命名规则
# 参数列表:括号中的变量名,表示调用时可以传递的值
# 函数体:缩进的代码块,包含具体的实现逻辑
# 返回值:通过return语句将结果返回给调用者
# 定义
# Python要求函数体代码必须缩进(通常为4个空格)
def square(x):
return x**2
print(square(2))
# 可以在函数内部定义文档字符串(docstring),用于描述函数的作用:
def square(x):
"""
求x的平方
"""
return x**2
# 参数类型
# 1.位置参数:位置参数是最基本的参数类型,调用函数时按照参数的位置一一对应传递。
# 特点:
# 参数的顺序很重要,不能颠倒
# 调用时必须提供所有必需参数
# 参数按位置顺序赋值
def add(a, b):
return a + b
result = add(1, 2)
print(result)
# 2.关键字参数:关键字参数允许你在调用函数时,通过"参数名=值"的形式传递参数,这样参数顺序就可以任意。
# 优点:
# 不用记住参数顺序
# 增加代码可读性
# 很适合带有默认参数的函数
def student_info(name, age, city):
return f"姓名{name},年龄{age},城市{city}"
print(student_info(age=18, name="小明", city="beijing"))
# 3.默认参数:默认参数是指在定义函数时为参数提供默认值。在调用函数时,如果对应参数没有传值,则会使用这个默认值。
# 注意事项:
# 默认参数必须出现在非默认参数之后
# 默认参数常用于大多数情况下使用同一个值的场景
def greet(name, msg="Hello"):
print(f"{msg}, {name}!")
greet("Alice") # 输出:Hello, Alice!
greet("Bob", msg="Hi") # 输出:Hi, Bob!
# 4.可变参数:可变参数用于当函数需要接受不定数量的位置参数时,通过在参数前加*来实现。
# 特点:
# *args不是必须叫args,但习惯上都叫args
# 所有传入的位置参数被收集到一个元组中
# 特别适合参数数量不确定时使用
def show_args(*args):
print(f"参数类型{type(args)}")
print(f"参数内容{args}")
show_args(1, 2, 4) # 参数类型<class 'tuple'> 参数内容(1, 2, 4)
show_args([1, 2, 3]) # 参数类型<class 'tuple'> 参数内容([1, 2, 3],)
show_args("123") # 参数类型<class 'tuple'> 参数内容('123',)
# 应用
def make_pizza(*foods):
print("制作一个披萨,添加以下配料:")
for food in foods:
print(f"-{food}")
make_pizza("蘑菇", "青椒", "芝士")
# 5.关键字可变参数:关键字可变参数允许函数接收任意数量的"关键字参数"。这些参数会被自动收集到一个字典中。
# **kwargs不是必须叫kwargs,习惯上都这么命名
# 多余的关键字参数汇集到一个字典里
# 常用于不确定会传入哪些命名参数时
def show_kwargs(**kwargs):
print(f"参数类型{type(kwargs)}")
print(f"参数内容{kwargs}")
show_kwargs(name="1", age=18) # 参数类型<class 'dict'> 参数内容{'name': '1', 'age': 18}
# 综合
def demo(a, *args, b=1, **kwargs):
print(f"a:{a}") # a:小明
print(f"args:{args}") # args:(20, 30)
print(f"b:{b}") # b:北京
print(f"kwargs:{kwargs}") # kwargs:{'x': '8', 'y': 10}
demo("小明", 20, 30, b="北京", x="8", y=10)
# 参数解包
# 在Python中,*和**不仅可以用于函数定义时接收可变参数,还可以用于参数解包。
def greet(name, age, city):
print(f"姓名: {name}, 年龄: {age}, 城市: {city}")
# 使用 * 解包列表
person_info = ["Alice", 25, "北京"]
greet(*person_info) # 等同于 greet("Alice", 25, "北京")
# 使用 * 解包元组
data = ("Bob", 30, "上海")
greet(*data) # 等同于 greet("Bob", 30, "上海")
# ** 用于解包字典类型
def create_profile(name, age, city, occupation):
print(f"姓名: {name}, 年龄: {age}, 城市: {city}, 职业: {occupation}")
# 使用 ** 解包字典
profile_data = {"name": "Charlie", "age": 28, "city": "广州", "occupation": "工程师"}
create_profile(**profile_data)
# 混合使用
def complex_function(a, b, c, d, e):
print(f"a: {a}, b: {b}, c: {c}, d: {d},e:{e}")
list_data = [1, 2]
dict_data = {"d": 10, "e": "小明"}
complex_function(*list_data, True, **dict_data)
# 返回值
# 返回单个值
def get_formatted_name(first_name, last_name):
full_name = f"{first_name}{last_name}"
return full_name
musician = get_formatted_name("", "")
print(musician) # 张三
# 返回多个值
def operate_numbers(a, b):
sum_result = a + b
diff_result = a - b
product_result = a * b
return sum_result, diff_result, product_result
# 接收元组
result = operate_numbers(10, 5)
print(result) # (15, 5, 50)
# 解包返回值
sum_val, diff_val, product_val = operate_numbers(10, 5)
print(f"Sum: {sum_val}, Difference: {diff_val}, Product: {product_val}")
def create_student_report(name, **scores):
report = {"name": name, "total_score": 0, "subjects": scores}
for key, score in scores.items():
print(f"{key}:{score}")
# # 计算总分
for score in scores.values():
report["total_score"] += score
# # 计算平均分
report["average"] = report["total_score"] / len(scores)
return report
student = create_student_report("Alice", **{"math": 95, "science": 87, "english": 92})
print(student)
# 函数文档和注释
# 文档字符串(Docstring
# 文档字符串是紧跟在函数定义后,用三引号包裹的字符串,用于描述函数的用途、参数说明、返回值类型等。
def calculate_circle_area(radius):
"""
计算圆的面积
参数:
radius (float): 圆的半径
返回:
float: 圆的面积
"""
import math
return math.pi * radius**2
# 查看文档字符串
print(calculate_circle_area.__doc__)
# 查看函数帮助
help(calculate_circle_area)
# 注释
# 注释是用#开头的说明性文字,用于解释代码片段的实现思路、注意事项或特殊用途
def safe_divide(a, b):
"""安全的除法函数"""
# 检查除数是否为零
if b == 0:
return "错误:除数不能为零"
# 执行除法运算
result = a / b
return result
# 变量作用域
# 作用域类型
# 作用域类型 描述 示例
# 局部作用域 变量在函数内部定义,只能在该函数内部使用 函数内的局部变量
# 全局作用域 变量在所有函数体外部定义,可以在整个模块里访问 模块级别的变量
# 嵌套作用域 内部函数可以访问外部函数中的变量 闭包中的外部变量
# 内置作用域 Python预先定义的内置标识符 len, range, print等
# LEGB原则
# Python采用LEGB原则查找变量:
# L: Local(本地作用域)
# E: Enclosing(嵌套函数的外部函数作用域)
# G: Global(全局作用域)
# B: Built-in(内置作用域)
name = "全局变量"
def outer():
name = "外部函数变量"
def inner():
name = "内部函数变量"
print(f"inner:{name}") # 输出"内部函数变量"
inner()
print(f"outer:{name}") # 输出"外部函数变量"
outer()
print(name) # 输出"全局变量"
# global关键字
# global关键字允许我们在函数内部声明某个变量为全局变量,从而可以在函数内部修改它。
# 注意事项:
# 没有global关键字时,在函数内对一个变量赋值会将其作为局部变量处理
# 使用global后,函数内的变量就直接引用外部全局变量
counter = 0
def increment():
global counter # 引用外部全局变量
counter += 1
increment()
increment()
print(counter) # 2
# nonlocal关键字
# nonlocal关键字用于在嵌套函数中声明变量来自最近的一层非全局作用域(外层函数)。
def outer():
x = "local"
def inner():
nonlocal x # 声明 x 来自外层作用域
x = "nonlocal"
print(f"inner:{x}") # inner:nonlocal
inner()
print(f"outer:{x}") # outer:nonlocal
outer()
# 高级函数特性
# 8.1.函数作为参数
# 函数不仅可以像变量一样赋值给其他变量,还可以作为参数传递给其他函数。
def apply_operation(numbers, operation):
"""对数字列表应用操作"""
return [operation(x) for x in numbers]
def square(x):
return x**2
def double(x):
return x * 2
numbers = [1, 2, 3, 4, 5]
squared = apply_operation(numbers, square)
doubled = apply_operation(numbers, double)
print(squared) # [1, 4, 9, 16, 25]
print(doubled) # [2, 4, 6, 8, 10]
# 嵌套函数
# 嵌套函数是指在一个函数内部定义另一个函数。内部函数可以访问外部函数的参数和局部变量。
# 用途:
# 实现闭包(closure
# 将某些逻辑封装到本地作用域
# 作为工厂函数创建带记忆的数据
def greet(name):
def format_message():
return f"Hello, {name}!"
return format_message()
print(greet("Alice")) # Hello, Alice!
# 闭包
# 闭包是指一个函数可以"记住"它被创建时的环境,即使在其外部函数已经执行完毕后,内部函数依然能够访问其外部作用域的变量。
# 特点:
# 内部函数引用了外部函数的局部变量
# 外部函数返回内部函数
# 内部函数可以访问外部函数的变量,即使外部函数已经执行完毕
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
# 装饰器
# 装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器常用于在不修改原函数代码的情况下,动态地为其添加新功能。
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@my_decorator
def say_hello():
print("Hello")
say_hello() # 函数执行前 Hello 函数执行后
# 带参数的装饰器
def logger(func):
def wrapper(*args, **kwargas):
print(f"调用函数{func.__name__},参数:{args}{kwargas}")
return func(*args, **kwargas)
return wrapper
@logger
def add(x, y, **kwargs):
a = x + y
b = sum(kwargs.values())
return a + b
print(add(1, 2, a=3, b=4))
# 匿名函数 (Lambda)
# 匿名函数(lambda表达式)是一种快速定义简单函数的方法,通常用于一些无需命名、只用一次的小函数场景。
# lambda 参数1, 参数2, ... : 表达式
# 基本 lambda 函数
# 特点:
# 只能包含表达式,不能包含语句
# 自动返回表达式的值
# 适合简单的函数逻辑
square = lambda x: x**2
print(square(5)) # 25
# 在排序中使用
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78},
]
# 按成绩排序
sorted_students = sorted(students, key=lambda x: x["grade"])
print(sorted_students)
# 在 map 中使用
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# 在 filter 中使用
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4]
# 递归函数
# 递归函数是函数调用自身来解决问题的方法,适合解决可以被分解为规模更小、相似子问题的任务。
# def func(params):
# if 终止条件:
# return 结果
# else:
# # 递归调用自身
# return func(更小规模的参数)
# 注意事项:
# 必须设置基线条件(终止条件),避免无限递归
# 递归深度有限制,可能导致栈溢出
# 对于规模较大的问题效率较低
def factorial(n):
"""计算阶乘的递归函数"""
if n == 0 or n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(5)) # 120
def fibonacci(n):
"""计算斐波那契数列"""
if n <= 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
for i in range(10):
print(fibonacci(i), end=" ") # 0 1 1 2 3 5 8 13 21 34
# 错误处理
# 在函数中进行错误处理可以提升程序的健壮性和用户体验。
# def 函数名(参数):
# try:
# # 可能抛出异常的操作
# except 异常类型1:
# # 异常类型1的处理代码
# except 异常类型2:
# # 异常类型2的处理代码
# else:
# # 没有发生异常时的代码
# finally:
# # 无论是否发生异常都执行
def safe_divide(a, b):
"""安全的除法函数"""
try:
result = a / b
except ZeroDivisionError:
return "错误:除数不能为零"
except TypeError:
return "错误:参数类型不正确"
else:
return result
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # 错误:除数不能为零
print(safe_divide(10, "a")) # 错误:参数类型不正确
# 最佳实践
# 14.1.函数设计原则
# 单一职责:每个函数只做一件事
# 描述性命名:使用有意义的函数名
# 保持简短:函数应该简短且专注
# 使用文档字符串:为函数添加适当的文档
# 避免副作用:函数不应该修改外部状态,除非明确需要
# 14.2.参数设计
# 合理使用默认参数:使函数更灵活
# 参数顺序:位置参数在前,默认参数在后
# 使用*args和kwargs**:提高函数灵活性
# 参数验证:在函数开始处验证参数
# 14.3.错误处理
# 处理异常:在适当的地方处理可能的错误
# 提供有意义的错误信息:帮助用户理解问题
# 使用try-except:优雅地处理异常情况
# 14.4.性能考虑
# 避免不必要的计算:将重复计算提取到函数外部
# 使用生成器:对于大数据集使用生成器函数
# 缓存结果:对于昂贵的计算考虑缓存
# 15.总结
# 函数是Python编程的核心概念,掌握函数的定义、调用、参数传递、返回值、作用域等概念对于编写高质量的Python代码至关重要。通过合理使用函数,我们可以:
# 提高代码的可重用性和可维护性
# 实现模块化编程
# 简化复杂问题的解决
# 提高代码的可读性和可测试性
# 掌握函数的高级特性如闭包、装饰器、递归等,能够让我们编写更加灵活和强大的Python程序。