Python高级特性
装饰器
装饰器的概念
装饰器是Python中一种强大的编程工具,它允许我们在不修改原函数代码的情况下,增强函数的功能。装饰器本质上是一个接收函数作为参数并返回新函数的函数。
基本装饰器
python
def decorator(func):
def wrapper():
print("函数执行前的操作")
func()
print("函数执行后的操作")
return wrapper
@decorator
def hello():
print("Hello, World!")
hello()
# 输出:
# 函数执行前的操作
# Hello, World!
# 函数执行后的操作def decorator(func):
def wrapper():
print("函数执行前的操作")
func()
print("函数执行后的操作")
return wrapper
@decorator
def hello():
print("Hello, World!")
hello()
# 输出:
# 函数执行前的操作
# Hello, World!
# 函数执行后的操作带参数的装饰器
python
def decorator_with_args(arg1, arg2):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"装饰器参数: {arg1}, {arg2}")
print("函数执行前的操作")
result = func(*args, **kwargs)
print("函数执行后的操作")
return result
return wrapper
return decorator
@decorator_with_args("参数1", "参数2")
def add(a, b):
return a + b
result = add(1, 2)
print(f"函数结果: {result}")
# 输出:
# 装饰器参数: 参数1, 参数2
# 函数执行前的操作
# 函数执行后的操作
# 函数结果: 3def decorator_with_args(arg1, arg2):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"装饰器参数: {arg1}, {arg2}")
print("函数执行前的操作")
result = func(*args, **kwargs)
print("函数执行后的操作")
return result
return wrapper
return decorator
@decorator_with_args("参数1", "参数2")
def add(a, b):
return a + b
result = add(1, 2)
print(f"函数结果: {result}")
# 输出:
# 装饰器参数: 参数1, 参数2
# 函数执行前的操作
# 函数执行后的操作
# 函数结果: 3类装饰器
python
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("类装饰器执行前的操作")
result = self.func(*args, **kwargs)
print("类装饰器执行后的操作")
return result
@Decorator
def multiply(a, b):
return a * b
result = multiply(3, 4)
print(f"函数结果: {result}")
# 输出:
# 类装饰器执行前的操作
# 类装饰器执行后的操作
# 函数结果: 12class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("类装饰器执行前的操作")
result = self.func(*args, **kwargs)
print("类装饰器执行后的操作")
return result
@Decorator
def multiply(a, b):
return a * b
result = multiply(3, 4)
print(f"函数结果: {result}")
# 输出:
# 类装饰器执行前的操作
# 类装饰器执行后的操作
# 函数结果: 12常用内置装饰器
- @property: 将方法转换为只读属性
- @staticmethod: 将方法转换为静态方法
- @classmethod: 将方法转换为类方法
- @functools.wraps: 保留原函数的元信息
python
import functools
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, new_value):
if new_value > 0:
self._value = new_value
@staticmethod
def static_method():
return "这是静态方法"
@classmethod
def class_method(cls):
return f"这是类方法,类名: {cls.__name__}"
# 使用functools.wraps保留原函数元信息
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapperimport functools
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, new_value):
if new_value > 0:
self._value = new_value
@staticmethod
def static_method():
return "这是静态方法"
@classmethod
def class_method(cls):
return f"这是类方法,类名: {cls.__name__}"
# 使用functools.wraps保留原函数元信息
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper生成器
生成器的概念
生成器是一种特殊的迭代器,它允许我们在循环中动态生成值,而不需要一次性将所有值存储在内存中。生成器使用yield关键字来产生值。
生成器函数
python
def generator_function(n):
for i in range(n):
yield i * 2
# 使用生成器
gen = generator_function(5)
# 方法1:使用next()函数
print(next(gen)) # 0
print(next(gen)) # 2
print(next(gen)) # 4
# 方法2:使用for循环
for value in gen:
print(value) # 6, 8def generator_function(n):
for i in range(n):
yield i * 2
# 使用生成器
gen = generator_function(5)
# 方法1:使用next()函数
print(next(gen)) # 0
print(next(gen)) # 2
print(next(gen)) # 4
# 方法2:使用for循环
for value in gen:
print(value) # 6, 8生成器表达式
python
# 生成器表达式
gen_expr = (i * 3 for i in range(5))
for value in gen_expr:
print(value) # 0, 3, 6, 9, 12
# 对比列表推导式(会一次性生成所有值)
list_comp = [i * 3 for i in range(5)]
print(list_comp) # [0, 3, 6, 9, 12]# 生成器表达式
gen_expr = (i * 3 for i in range(5))
for value in gen_expr:
print(value) # 0, 3, 6, 9, 12
# 对比列表推导式(会一次性生成所有值)
list_comp = [i * 3 for i in range(5)]
print(list_comp) # [0, 3, 6, 9, 12]生成器的应用场景
- 处理大数据集:避免一次性加载所有数据到内存
- 无限序列:生成无限序列,如斐波那契数列
- 惰性计算:只在需要时才计算值
python
# 生成无限斐波那契数列
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 使用islice限制输出数量
from itertools import islice
fib = fibonacci()
for num in islice(fib, 10):
print(num) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34# 生成无限斐波那契数列
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 使用islice限制输出数量
from itertools import islice
fib = fibonacci()
for num in islice(fib, 10):
print(num) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34迭代器
迭代器的概念
迭代器是一种对象,它实现了迭代器协议,即__iter__()和__next__()方法。迭代器允许我们逐个访问容器中的元素,而不需要知道容器的内部结构。
迭代器协议
__iter__():返回迭代器对象本身__next__():返回容器中的下一个元素,如果没有更多元素,则抛出StopIteration异常
自定义迭代器
python
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
value = self.data[self.index]
self.index += 1
return value
else:
raise StopIteration
# 使用自定义迭代器
my_iter = MyIterator([1, 2, 3, 4, 5])
for value in my_iter:
print(value) # 1, 2, 3, 4, 5class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
value = self.data[self.index]
self.index += 1
return value
else:
raise StopIteration
# 使用自定义迭代器
my_iter = MyIterator([1, 2, 3, 4, 5])
for value in my_iter:
print(value) # 1, 2, 3, 4, 5内置迭代器
Python中的许多内置数据结构都实现了迭代器协议,如列表、元组、字典、集合和字符串。
python
# 列表迭代器
my_list = [1, 2, 3]
list_iter = iter(my_list)
print(next(list_iter)) # 1
print(next(list_iter)) # 2
# 字典迭代器
my_dict = {"a": 1, "b": 2}
# 迭代字典的键
dict_iter = iter(my_dict)
print(next(dict_iter)) # a
# 迭代字典的值
value_iter = iter(my_dict.values())
print(next(value_iter)) # 1
# 迭代字典的键值对
item_iter = iter(my_dict.items())
print(next(item_iter)) # ('a', 1)# 列表迭代器
my_list = [1, 2, 3]
list_iter = iter(my_list)
print(next(list_iter)) # 1
print(next(list_iter)) # 2
# 字典迭代器
my_dict = {"a": 1, "b": 2}
# 迭代字典的键
dict_iter = iter(my_dict)
print(next(dict_iter)) # a
# 迭代字典的值
value_iter = iter(my_dict.values())
print(next(value_iter)) # 1
# 迭代字典的键值对
item_iter = iter(my_dict.items())
print(next(item_iter)) # ('a', 1)迭代器与生成器的关系
- 生成器是一种特殊的迭代器
- 生成器自动实现了迭代器协议
- 生成器使用
yield关键字,而迭代器需要手动实现__iter__()和__next__()方法
高级迭代工具
itertools模块
itertools模块提供了许多用于高效迭代的工具函数。
python
import itertools
# 1. 无限迭代器
# count: 从指定数字开始,无限递增
for i in itertools.islice(itertools.count(10, 2), 5):
print(i) # 10, 12, 14, 16, 18
# cycle: 无限循环迭代一个序列
for i, val in enumerate(itertools.islice(itertools.cycle(["A", "B", "C"]), 5)):
print(f"{i}: {val}") # 0:A, 1:B, 2:C, 3:A, 4:B
# repeat: 重复一个值指定次数
for val in itertools.repeat("Hello", 3):
print(val) # Hello, Hello, Hello
# 2. 组合迭代器
# product: 笛卡尔积
for combo in itertools.product([1, 2], ["a", "b"]):
print(combo) # (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')
# permutations: 排列
for perm in itertools.permutations([1, 2, 3], 2):
print(perm) # (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)
# combinations: 组合
for comb in itertools.combinations([1, 2, 3], 2):
print(comb) # (1, 2), (1, 3), (2, 3)
# 3. 迭代器操作
# chain: 连接多个迭代器
for val in itertools.chain([1, 2], [3, 4], [5, 6]):
print(val) # 1, 2, 3, 4, 5, 6
# groupby: 分组
from operator import itemgetter
data = [
{"name": "张三", "age": 20},
{"name": "李四", "age": 20},
{"name": "王五", "age": 21},
{"name": "赵六", "age": 21}
]
for age, group in itertools.groupby(data, key=itemgetter("age")):
print(f"年龄 {age} 的人:")
for person in group:
print(f" {person['name']}")import itertools
# 1. 无限迭代器
# count: 从指定数字开始,无限递增
for i in itertools.islice(itertools.count(10, 2), 5):
print(i) # 10, 12, 14, 16, 18
# cycle: 无限循环迭代一个序列
for i, val in enumerate(itertools.islice(itertools.cycle(["A", "B", "C"]), 5)):
print(f"{i}: {val}") # 0:A, 1:B, 2:C, 3:A, 4:B
# repeat: 重复一个值指定次数
for val in itertools.repeat("Hello", 3):
print(val) # Hello, Hello, Hello
# 2. 组合迭代器
# product: 笛卡尔积
for combo in itertools.product([1, 2], ["a", "b"]):
print(combo) # (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')
# permutations: 排列
for perm in itertools.permutations([1, 2, 3], 2):
print(perm) # (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)
# combinations: 组合
for comb in itertools.combinations([1, 2, 3], 2):
print(comb) # (1, 2), (1, 3), (2, 3)
# 3. 迭代器操作
# chain: 连接多个迭代器
for val in itertools.chain([1, 2], [3, 4], [5, 6]):
print(val) # 1, 2, 3, 4, 5, 6
# groupby: 分组
from operator import itemgetter
data = [
{"name": "张三", "age": 20},
{"name": "李四", "age": 20},
{"name": "王五", "age": 21},
{"name": "赵六", "age": 21}
]
for age, group in itertools.groupby(data, key=itemgetter("age")):
print(f"年龄 {age} 的人:")
for person in group:
print(f" {person['name']}")推导式
除了生成器表达式,Python还支持列表、字典和集合推导式。
python
# 列表推导式
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers if x % 2 == 0]
print(squares) # [4, 16]
# 字典推导式
dict_squares = {x: x**2 for x in numbers if x % 2 != 0}
print(dict_squares) # {1: 1, 3: 9, 5: 25}
# 集合推导式
set_squares = {x**2 for x in numbers}
print(set_squares) # {1, 4, 9, 16, 25}# 列表推导式
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers if x % 2 == 0]
print(squares) # [4, 16]
# 字典推导式
dict_squares = {x: x**2 for x in numbers if x % 2 != 0}
print(dict_squares) # {1: 1, 3: 9, 5: 25}
# 集合推导式
set_squares = {x**2 for x in numbers}
print(set_squares) # {1, 4, 9, 16, 25}上下文管理器
上下文管理器的概念
上下文管理器是一种用于管理资源的对象,它定义了在进入和退出代码块时应该执行的操作。上下文管理器通常与with语句一起使用,用于确保资源的正确获取和释放。
使用with语句
python
# 文件操作中的上下文管理器
with open("file.txt", "w") as f:
f.write("Hello, World!")
# 文件自动关闭,无需手动调用f.close()
# 数据库连接中的上下文管理器
import sqlite3
with sqlite3.connect(":memory:") as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE test (id INTEGER, name TEXT)")
cursor.execute("INSERT INTO test VALUES (1, '张三')")
conn.commit()
# 连接自动关闭# 文件操作中的上下文管理器
with open("file.txt", "w") as f:
f.write("Hello, World!")
# 文件自动关闭,无需手动调用f.close()
# 数据库连接中的上下文管理器
import sqlite3
with sqlite3.connect(":memory:") as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE test (id INTEGER, name TEXT)")
cursor.execute("INSERT INTO test VALUES (1, '张三')")
conn.commit()
# 连接自动关闭自定义上下文管理器
python
class MyContextManager:
def __enter__(self):
print("进入上下文管理器")
return "上下文管理器返回值"
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文管理器")
# 如果发生异常,可以在这里处理
if exc_type:
print(f"发生异常: {exc_type}, {exc_val}")
# 返回True表示异常已处理,不会向上传播
return False
# 使用自定义上下文管理器
with MyContextManager() as cm:
print(f"在with语句中,获取到的值: {cm}")
# 可以在这里执行操作class MyContextManager:
def __enter__(self):
print("进入上下文管理器")
return "上下文管理器返回值"
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文管理器")
# 如果发生异常,可以在这里处理
if exc_type:
print(f"发生异常: {exc_type}, {exc_val}")
# 返回True表示异常已处理,不会向上传播
return False
# 使用自定义上下文管理器
with MyContextManager() as cm:
print(f"在with语句中,获取到的值: {cm}")
# 可以在这里执行操作contextlib模块
contextlib模块提供了创建上下文管理器的工具函数。
python
from contextlib import contextmanager
@contextmanager
def my_context_manager():
print("进入上下文管理器")
try:
yield "上下文管理器返回值"
except Exception as e:
print(f"发生异常: {e}")
# 可以选择重新抛出异常或处理
raise
finally:
print("退出上下文管理器")
# 使用装饰器创建的上下文管理器
with my_context_manager() as cm:
print(f"在with语句中,获取到的值: {cm}")from contextlib import contextmanager
@contextmanager
def my_context_manager():
print("进入上下文管理器")
try:
yield "上下文管理器返回值"
except Exception as e:
print(f"发生异常: {e}")
# 可以选择重新抛出异常或处理
raise
finally:
print("退出上下文管理器")
# 使用装饰器创建的上下文管理器
with my_context_manager() as cm:
print(f"在with语句中,获取到的值: {cm}")闭包
闭包的概念
闭包是指一个函数可以记住并访问其词法作用域,即使该函数在其词法作用域之外执行。闭包通常用于创建带有私有状态的函数。
闭包的示例
python
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
# 创建闭包
add_five = outer_function(5)
# 调用闭包
print(add_five(3)) # 8
print(add_five(10)) # 15
# 创建另一个闭包
add_ten = outer_function(10)
print(add_ten(3)) # 13def outer_function(x):
def inner_function(y):
return x + y
return inner_function
# 创建闭包
add_five = outer_function(5)
# 调用闭包
print(add_five(3)) # 8
print(add_five(10)) # 15
# 创建另一个闭包
add_ten = outer_function(10)
print(add_ten(3)) # 13闭包的应用场景
- 创建私有变量
- 实现装饰器
- 延迟计算
- 实现回调函数
python
# 使用闭包创建计数器
def create_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
def decrement():
nonlocal count
count -= 1
return count
def get_count():
return count
return increment, decrement, get_count
# 使用计数器
inc, dec, get = create_counter()
print(inc()) # 1
print(inc()) # 2
print(dec()) # 1
print(get()) # 1# 使用闭包创建计数器
def create_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
def decrement():
nonlocal count
count -= 1
return count
def get_count():
return count
return increment, decrement, get_count
# 使用计数器
inc, dec, get = create_counter()
print(inc()) # 1
print(inc()) # 2
print(dec()) # 1
print(get()) # 1实用装饰器模式
重试装饰器
python
import functools
import time
def retry(max_attempts=3, delay=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"第 {attempt} 次失败: {e},{delay}秒后重试...")
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=0.5)
def fetch_data(url: str) -> dict:
# 模拟网络请求
...import functools
import time
def retry(max_attempts=3, delay=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"第 {attempt} 次失败: {e},{delay}秒后重试...")
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=0.5)
def fetch_data(url: str) -> dict:
# 模拟网络请求
...计时装饰器
python
import functools
import time
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} 耗时: {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
slow_function() # 输出: slow_function 耗时: 1.0002simport functools
import time
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} 耗时: {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
slow_function() # 输出: slow_function 耗时: 1.0002s单例装饰器
python
import functools
def singleton(cls):
instances = {}
@functools.wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
print("创建数据库连接")
db1 = Database() # 打印: 创建数据库连接
db2 = Database() # 不打印,返回已存在的实例
print(db1 is db2) # Trueimport functools
def singleton(cls):
instances = {}
@functools.wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
print("创建数据库连接")
db1 = Database() # 打印: 创建数据库连接
db2 = Database() # 不打印,返回已存在的实例
print(db1 is db2) # True缓存装饰器(lru_cache)
python
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# fibonacci(100) 会非常快,结果被缓存
print(fibonacci(100))
# 查看缓存信息
print(fibonacci.cache_info()) # CacheInfo(hits=98, misses=101, maxsize=128, currsize=101)from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# fibonacci(100) 会非常快,结果被缓存
print(fibonacci(100))
# 查看缓存信息
print(fibonacci.cache_info()) # CacheInfo(hits=98, misses=101, maxsize=128, currsize=101)总结
Python的高级特性包括:
- 装饰器:增强函数功能,无需修改原代码
- 生成器:动态生成值,节省内存
- 迭代器:逐个访问容器元素,实现迭代器协议
- 上下文管理器:管理资源,确保正确获取和释放
- 闭包:记住并访问词法作用域
这些高级特性使Python代码更加简洁、高效和可维护,是Python编程中的重要工具。
Cao Note