1. 装饰器 (Decorators) 装饰器的本质是一个接受函数作为参数并返回新函数的高阶函数 。
能够在不修改原始函数代码的情况下,动态地增加函数的功能。
1.1 简单样例 1 2 3 4 5 6 7 8 9 10 11 12 13 def decorator(func): def wrapper(*args, **kwargs): print("Before function call") result = func(*args, **kwargs) print("After function call") return result return wrapper @decorator def greet(name): print(f"Hello, {name}") greet("Alice")
1.2 带参数的装饰器 若装饰器需要接受参数,需再嵌套一层函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def repeat(n): def decorator(func): def wrapper(*args, **kwargs): for _ in range(n): result = func(*args, **kwargs) return result return wrapper return decorator @repeat(3) def say_hello(): print("Hello!") say_hello() Hello! Hello! Hello!
1.3 类装饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class CounterDecorator: def __init__(self, func): self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.func.__name__} 已被调用 {self.count} 次") return self.func(*args, **kwargs) @CounterDecorator def example(): print("执行函数") example() example() example 已被调用 1 次 执行函数 example 已被调用 2 次 执行函数
1.4 保留函数元数据 使用装饰器对函数进行包装的本质是:被装饰的函数会被替换为装饰器内部的wrapper函数
wrapper函数会丢失原函数的元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 def a_decorator(func): def wrapper(*args, **kwargs): """A wrapper function""" # Extend some capabilities of func func() return wrapper @a_decorator def first_function(): """This is docstring for first function""" print("first function") @a_decorator def second_function(a): """This is docstring for second function""" print("second function") print(first_function.__name__) print(first_function.__doc__) print(second_function.__name__) print(second_function.__doc__) wrapper A wrapper function wrapper A wrapper function
使用functools.wrap
保留函数元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import functools def a_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): """A wrapper function""" # Extend some capabilities of func func() return wrapper @a_decorator def first_function(): """This is docstring for first function""" print("first function") @a_decorator def second_function(a): """This is docstring for second function""" print("second function") print(first_function.__name__) print(first_function.__doc__) print(second_function.__name__) print(second_function.__doc__) first_function This is docstring for first function second_function This is docstring for second function
1.4 常用Decorators 1.4.1 @property @property
会将一个方法转换为属性,实现面向对象的属性封装和验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): return self._radius @radius.setter def radius(self, value): if value < 0: raise ValueError("半径不能为负数") self._radius = value c = Circle(5) print(c.radius) # 5 (直接访问属性) c.radius = 10 # 调用 setter 方法 c.radius = -1 # 抛出 ValueError
1.4.2 @staticmethod 与 @classmethod 类方法和静态方法是 Python 中用于类的函数,区别在于类方法的第一个参数是类对象cls
,而静态方法则与类和实例没有直接关联。
类方法用于操作类级别的数据(如工厂方法)。
静态方法用于与类的状态无关的功能(如数学运算、数据处理)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class MyClass: cnt = 0 @classmethod def class_method(cls): print(f"Class method called: {cls.cnt}") @staticmethod def static_method(): print(f"Static method called: {MyClass.cnt}") MyClass.class_method() MyClass.static_method() Class method called: 0 Static method called: 0
lru_cache
装饰器可以用来为一个函数添加一个缓存,存储函数的输入和对应的输出。如果函数被调用,并且给出了已经缓存过的输入,那么函数就不会被调用,而是直接从缓存中获取对应的输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import functools import time # @functools.lru_cache(maxsize=None) # 使用缓存,maxsize=None 表示无限制缓存大小 def fibonacci(n): if n < 0: raise ValueError("Input must be a non-negative integer.") elif n == 0: return 0 elif n == 1: return 1 else: return fibonacci(n - 1) + fibonacci(n - 2) start = time.time() fibonacci(30) end1 = time.time() print(end1 - start) 0.32143115997314453 去掉注释 0.0
2. 生成器 (Generators) 生成器是一种特殊的迭代器,它通过函数实现。与普通函数不同,生成器函数每次执行到 yield
时,函数会暂停执行,返回一个值,并在下次调用时从上次暂停的位置继续执行。
大量数据的惰性加载
网络数据的流式返回,如AI问答的流式返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import time def count_up_to(max): count = 1 while count <= max: time.sleep(1) yield count count += 1 gen = count_up_to(5) print(gen) for num in gen: print(time.perf_counter()) <generator object count_up_to at 0x0000022260E6DA50> 1.1235322 2.125579 3.1393956 4.1479524 5.1612428
3. 上下文管理器 (Context Managers) 上下文管理器(Context Manager)是一种用于管理资源(如文件、网络连接、锁等)的机制,确保资源在使用后能够正确地被清理或释放。上下文管理器的核心是 with
语句,它提供了一种优雅的方式来处理资源的获取和释放,而无需手动管理资源的生命周期。
3.1 工作原理 上下文管理器的核心是 with
语句。with
语句会自动调用上下文管理器的两个特殊方法:
__enter__()
:在进入上下文时被调用,用于初始化资源。
__exit__()
:在退出上下文时被调用,用于清理资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class MyContextManager: def __enter__(self): print("Entering the context") return self def __exit__(self, exc_type, exc_value, traceback): print("Exiting the context") if exc_type: print(f"exc_type={exc_type}, exc_value={exc_value}, traceback={traceback}") return True # 不抛出异常 with MyContextManager() as cm: print(1/0) Entering the context Exiting the context exc_type=<class 'ZeroDivisionError'>, exc_value=division by zero, traceback=<traceback object at 0x000001BBECDCA5C0>
3.2 内置上下文管理器 3.2.1 文件 1 2 3 # 文件在退出上下文时自动关闭 with open("example.txt", "w") as file: file.write("Hello, World!")
3.2.2 线程锁 1 2 3 4 5 import threading lock = threading.Lock() with lock: print("Critical section")
4. 函数式编程 (Functional Programming) 函数式编程的核心思想是将程序分解为一系列纯函数(pure functions),并通过函数组合来实现复杂的逻辑。Python支持函数式编程特性,如 map
、filter
、reduce
和匿名函数(lambda
)。
4.1 lambda 创建匿名函数,通常用于简化代码。
lambda arguments: expression
1 2 3 4 # 按字符串长度排序 words = ["apple", "banana", "cherry", "date"] sorted_words = sorted(words, key=lambda x: len(x)) print(sorted_words) # 输出: ['date', 'apple', 'cherry', 'banana']
4.2 map 将一个函数应用于一个或多个可迭代对象的所有元素,并返回一个惰性迭代器 。
map(function, iterable, …)
1 2 3 4 5 numbers = [1, 2, 3, 4, 5] squared = map(lambda x: x**2, numbers) print(squared) <map object at 0x0000023BEF4E5910>
4.3 reduce reduce
用于将一个二元函数(接受两个参数的函数)累积地应用于一个可迭代对象的所有元素,从而将整个序列“折叠”成一个单一的结果。
在 Python 3 中,reduce
不再是内置函数,而是被移到了 functools
模块中。因此,使用 reduce
时需要先导入 functools
模块。
reduce(function, iterable[, initializer])
1 2 3 4 5 6 7 from functools import reduce numbers = [1, 2, 3, 4, 5] result = reduce(lambda x, y: x + y, numbers) print(result) 15
4.4 filter 用于从可迭代对象中筛选出满足特定条件的元素。
工作原理是将一个布尔函数应用于可迭代对象的每个元素,然后返回一个惰性迭代器 ,其中包含所有使布尔函数返回 True
的元素。
1 2 3 4 5 6 7 numbers = [1, 2, 3, 4, 5] result = filter(lambda x: x & 1 == 0, numbers) print(result) print(list(result)) <filter object at 0x00000121065F5910> [2, 4]
5. 解包 解包(Unpacking)是一种非常强大且灵活的特性,将可迭代对象(如列表、元组、字典等)中的元素分配给多个变量
使用 *
和 **
将可迭代对象解包为函数的参数
1 2 3 4 5 6 7 8 9 10 11 12 def add(a, b, c): return a + b + c # 使用 * 解包列表 data = [1, 2, 3] result = add(*data) print(result) # 输出: 6 # 使用 ** 解包字典 config = {"a": 1, "b": 2, "c": 3} result = add(**config) print(result) # 输出: 6
参考 Python | functools.wraps() function - GeeksforGeeks
map/reduce - Python教程 - 廖雪峰的官方网站