进阶-python函数相关
6 minute read
Python 函数全面详解
一、函数基础概念
1. 什么是函数?
函数是可重用的代码块,用于执行特定任务。它具有以下特点:
- 接收输入(参数)
- 执行操作
- 返回输出(返回值)
- 提高代码的模块性和可重用性
2. 函数定义与调用
# 定义函数
def greet(name):
"""打印问候语(文档字符串)"""
return f"Hello, {name}!"
# 调用函数
result = greet("Alice")
print(result) # Hello, Alice!
# 无参数函数
def say_hello():
print("Hello World!")
# 无返回值函数(返回None)
def do_nothing():
pass
二、函数参数详解
1. 参数类型对比
| 参数类型 |
语法 |
描述 |
示例 |
| 位置参数 |
def func(a, b) |
按位置传递 |
func(1, 2) |
| 关键字参数 |
func(a=1, b=2) |
按参数名传递 |
func(b=2, a=1) |
| 默认参数 |
def func(a, b=5) |
提供默认值 |
func(1) → a=1, b=5 |
| 可变位置参数 |
def func(*args) |
接收任意数量位置参数 |
func(1,2,3) → args=(1,2,3) |
| 可变关键字参数 |
def func(**kwargs) |
接收任意数量关键字参数 |
func(a=1,b=2) → kwargs={'a':1,'b':2} |
| 仅限关键字参数 |
def func(*, a, b) 或 def func(*args, a, b) |
必须用关键字传递 |
func(a=1, b=2) |
| 仅限位置参数 |
def func(a, b, /) |
必须用位置传递 |
func(1, 2) |
2. 完整参数语法
def complex_func(pos1, pos2, /, pos_or_kw, *, kw1, kw2=10):
"""
参数说明:
- pos1, pos2: 仅限位置参数
- pos_or_kw: 位置或关键字参数
- kw1, kw2: 仅限关键字参数(kw2有默认值)
"""
print(f"pos1={pos1}, pos2={pos2}, pos_or_kw={pos_or_kw}, kw1={kw1}, kw2={kw2}")
# 调用示例
complex_func(1, 2, 3, kw1=4) # 正确
complex_func(1, 2, pos_or_kw=3, kw1=4) # 正确
# complex_func(1, 2, 3, 4) # 错误:kw1必须用关键字
3. 可变参数示例
# *args 接收任意数量的位置参数
def sum_all(*numbers):
"""计算所有数字的和"""
return sum(numbers)
print(sum_all(1, 2, 3, 4, 5)) # 15
print(sum_all(10, 20)) # 30
# **kwargs 接收任意数量的关键字参数
def print_info(**info):
"""打印所有关键字参数"""
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="Alice", age=25, city="Beijing")
# 混合使用
def mixed_func(a, b, *args, option=True, **kwargs):
"""混合所有参数类型"""
print(f"a={a}, b={b}, args={args}, option={option}, kwargs={kwargs}")
三、函数返回值
1. 返回多个值
def get_stats(numbers):
"""返回统计信息:最小值、最大值、平均值"""
if not numbers:
return None
minimum = min(numbers)
maximum = max(numbers)
average = sum(numbers) / len(numbers)
# 返回元组(多个值)
return minimum, maximum, average
# 接收多个返回值
min_val, max_val, avg_val = get_stats([1, 2, 3, 4, 5])
# 返回字典
def get_person():
"""返回字典包含多个值"""
return {
"name": "Alice",
"age": 25,
"city": "Beijing"
}
2. 返回函数
# 函数作为返回值
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
四、变量作用域
1. 作用域层次
# 全局变量
global_var = "I'm global"
def outer_function():
# 闭包作用域变量
outer_var = "I'm in outer function"
def inner_function():
# 局部变量
local_var = "I'm local"
# 访问所有作用域
print(local_var) # 局部
print(outer_var) # 闭包
print(global_var) # 全局
print(__name__) # 内置
inner_function()
# 全局作用域
print(global_var)
# print(outer_var) # 错误:不可访问
2. global 和 nonlocal
# global 关键字
counter = 0
def increment():
global counter # 声明使用全局变量
counter += 1
return counter
# nonlocal 关键字
def outer():
x = 10
def inner():
nonlocal x # 声明使用外层函数的变量
x += 5
return x
return inner()
五、函数作为对象
1. 函数是一等公民
# 1. 函数可以赋值给变量
def say_hello(name):
return f"Hello, {name}!"
greeting = say_hello # 函数赋值
print(greeting("Bob")) # 通过变量调用
# 2. 函数可以作为参数传递
def apply_operation(func, value):
"""将函数应用于值"""
return func(value)
def square(x):
return x * x
result = apply_operation(square, 5) # 25
# 3. 函数可以作为返回值
def get_operation(op_type):
"""根据操作类型返回函数"""
if op_type == "add":
return lambda x, y: x + y
elif op_type == "multiply":
return lambda x, y: x * y
else:
return None
2. 函数属性
def example_func(x, y=10):
"""示例函数,用于演示属性"""
return x + y
# 查看函数属性
print(example_func.__name__) # 函数名: 'example_func'
print(example_func.__doc__) # 文档字符串
print(example_func.__module__) # 模块名
print(example_func.__defaults__) # 默认参数值: (10,)
print(example_func.__code__) # 字节码对象
# 自定义函数属性
example_func.author = "Alice"
example_func.version = "1.0"
六、Lambda表达式
1. Lambda 基础
# Lambda 语法: lambda arguments: expression
square = lambda x: x * x
add = lambda x, y: x + y
# 立即调用
result = (lambda x: x + 1)(5) # 6
# 在列表推导式中使用
numbers = [1, 2, 3, 4, 5]
squares = [(lambda x: x**2)(n) for n in numbers]
2. Lambda 与高阶函数
# 与 map 一起使用
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16, 25]
# 与 filter 一起使用
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
# 与 sorted 一起使用
pairs = [(1, 5), (3, 2), (2, 8)]
sorted_pairs = sorted(pairs, key=lambda x: x[1]) # 按第二个元素排序
七、装饰器
1. 装饰器基础
# 简单装饰器
def my_decorator(func):
"""装饰器:在函数调用前后添加打印"""
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
# 使用装饰器
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# Before function call
# Hello!
# After function call
2. 带参数的装饰器
# 带参数的装饰器
def repeat(num_times):
"""重复执行函数指定次数"""
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(num_times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
# 输出三次: Hello, Alice!
3. 类装饰器
# 类装饰器
class Timer:
"""计时装饰器"""
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} took {end-start:.4f} seconds")
return result
@Timer
def slow_function():
import time
time.sleep(1)
return "Done"
slow_function() # 输出执行时间
八、生成器和迭代器
1. 生成器函数
# 使用 yield 创建生成器
def count_up_to(max_num):
"""生成从1到max_num的数字"""
count = 1
while count <= max_num:
yield count
count += 1
# 使用生成器
counter = count_up_to(5)
for num in counter:
print(num) # 1, 2, 3, 4, 5
# 生成器表达式
squares = (x**2 for x in range(5))
for square in squares:
print(square) # 0, 1, 4, 9, 16
2. 协程
# 使用 yield 接收值的生成器
def coroutine():
"""协程示例"""
print("Starting coroutine")
while True:
value = yield
print(f"Received: {value}")
# 使用协程
co = coroutine()
next(co) # 启动协程
co.send(10) # Received: 10
co.send(20) # Received: 20
九、递归函数
1. 递归基础
# 阶乘函数
def factorial(n):
"""计算阶乘(递归实现)"""
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
# 斐波那契数列
def fibonacci(n):
"""计算斐波那契数列(递归实现)"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10)) # 55
2. 尾递归优化
# 尾递归优化版本
def factorial_tail(n, accumulator=1):
"""尾递归阶乘函数"""
if n <= 1:
return accumulator
return factorial_tail(n-1, n * accumulator)
# 使用递归深度限制
import sys
sys.setrecursionlimit(10000) # 设置递归深度限制
十、函数注解
1. 类型注解
# 函数注解
def add(x: int, y: int) -> int:
"""返回两个整数的和"""
return x + y
# 带有复杂类型注解
from typing import List, Dict, Optional, Union
def process_data(
items: List[str],
config: Optional[Dict[str, Union[int, str]]] = None
) -> Dict[str, List[str]]:
"""处理数据函数"""
if config is None:
config = {}
return {item: [item] for item in items}
# 变量类型注解
name: str = "Alice"
age: int = 25
scores: List[int] = [85, 90, 78]
2. 类型检查
# 使用 mypy 进行类型检查
# 在命令行运行: mypy your_script.py
from typing import TypeVar, Callable
T = TypeVar('T')
def apply_to_all(func: Callable[[T], T], items: List[T]) -> List[T]:
"""将函数应用于列表所有元素"""
return [func(item) for item in items]
十一、内置高阶函数
| 函数 |
描述 |
示例 |
map(func, iterable) |
对可迭代对象的每个元素应用函数 |
map(str.upper, ['a','b']) → ['A','B'] |
filter(func, iterable) |
筛选满足条件的元素 |
filter(lambda x: x>0, [-1,0,1]) → [1] |
reduce(func, iterable) |
累积计算 |
reduce(lambda x,y: x+y, [1,2,3]) → 6 |
sorted(iterable, key=func) |
排序 |
sorted(['abc','a','ab'], key=len) → ['a','ab','abc'] |
min(iterable, key=func) |
最小值 |
min(['abc','a','ab'], key=len) → 'a' |
max(iterable, key=func) |
最大值 |
max(['abc','a','ab'], key=len) → 'abc' |
十二、偏函数
from functools import partial
# 创建偏函数
def power(base, exponent):
return base ** exponent
# 平方函数
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(3)) # 27
# 固定部分参数
def greet(greeting, name):
return f"{greeting}, {name}!"
say_hello = partial(greet, "Hello")
say_hi = partial(greet, "Hi")
print(say_hello("Alice")) # Hello, Alice!
print(say_hi("Bob")) # Hi, Bob!
十三、函数式编程
1. 不可变性
# 使用不可变数据结构
from functools import reduce
from typing import List
# 纯函数示例
def pure_multiply(numbers: List[int], factor: int) -> List[int]:
"""纯函数:不修改输入,返回新列表"""
return [n * factor for n in numbers]
# 函数组合
def compose(f, g):
"""函数组合:(f ∘ g)(x) = f(g(x))"""
return lambda x: f(g(x))
# 使用
add_one = lambda x: x + 1
square = lambda x: x * x
add_one_then_square = compose(square, add_one)
print(add_one_then_square(5)) # 36
十四、异步函数
import asyncio
# 异步函数
async def fetch_data():
"""模拟异步获取数据"""
print("开始获取数据...")
await asyncio.sleep(2) # 模拟IO操作
print("数据获取完成")
return {"data": "some data"}
async def process_data():
"""异步处理数据"""
data = await fetch_data()
print(f"处理数据: {data}")
return data
# 运行异步函数
async def main():
result = await process_data()
print(f"结果: {result}")
# Python 3.7+
asyncio.run(main())
十五、最佳实践
1. 设计原则
- 单一职责:每个函数只做一件事
- 短小精悍:函数应该简短(通常不超过20行)
- 明确命名:函数名应清晰表达其功能
- 减少副作用:尽量使用纯函数
- 合理抽象:适当抽象重复代码
2. 性能优化
- 避免不必要的递归
- 使用生成器处理大数据流
- 缓存重复计算结果
- 使用局部变量加速访问
- 考虑使用内置函数
3. 可读性建议
- 编写清晰的文档字符串
- 使用类型注解
- 保持参数数量合理(一般不超过5个)
- 避免深层嵌套
- 适当使用装饰器
十六、常见模式
# 1. 单例模式
def singleton(cls):
"""单例装饰器"""
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
# 2. 策略模式
class Strategy:
"""策略模式示例"""
def execute(self, data):
pass
class AddStrategy(Strategy):
def execute(self, a, b):
return a + b
class MultiplyStrategy(Strategy):
def execute(self, a, b):
return a * b
# 3. 回调模式
def fetch_data(callback):
"""获取数据后调用回调函数"""
data = {"result": "success"}
callback(data)
def handle_data(data):
print(f"处理数据: {data}")
fetch_data(handle_data)