Python高级语法
2025-02-25 23:05:17 # Python

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

1.4.3 @functools.lru_cache

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支持函数式编程特性,如 mapfilterreduce 和匿名函数(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教程 - 廖雪峰的官方网站