在 Python 中,装饰器(decorator)是一种特殊的函数或类,用于在不修改原始代码的情况下,动态地修改或增强函数、方法或类的行为。
函数:独立的代码块,可以在任何地方定义和调用。
方法:类中的函数,属于类的实例或类本身。
类:用于定义对象的蓝图,包含属性和方法。
下面将记录学习过程中,遇到的常见装饰器用法。
1. 函数装饰器#
在定义普通函数装饰器的过程中,一个装饰器通常是一个函数,接收另一个函数作为参数,并返回一个新的函数。这个新函数包含了对原始函数的调用以及新增的功能。
1.1 示例用法#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Function {func.__name__} is called with {args} and {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_decorator
def add(a, b):
return a + b
add(3, 4)
# Function add is called with (3, 4) and {}
# 7
|
*args
和 **kwargs
用于处理不定数量的参数。
- 前者将可变数量的非关键字参数打包成一个元组;
- 后者将可变数量的关键字参数打包成一个字典。
2. 方法装饰器#
方法装饰器是用于装饰类方法的函数,它们可以在不修改方法代码的情况下扩展或改变方法的行为。
2.1 @staticmethod与@classmethod#
- @staticmethod:定义静态方法,不需要传递实例 (
self
) 或类 (cls
) 作为参数。
1
2
3
4
5
6
7
8
|
class Calculator:
@staticmethod
def add(x, y):
return x + y
# 直接通过类名 Calculator 调用 add 方法
Calculator.add(5, 3)
# 先创建 Calculator 类的一个实例,再通过实例调用 add 方法。
Calculator().add(5, 3)
|
- @classmethod:用于定义类方法,类方法的第一个参数是类对象 (
cls
),而不是实例 (self
)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def from_tuple(cls, coords):
return cls(coords[0], coords[1])
@classmethod
def from_string(cls, coord_string):
x, y = map(int, coord_string.split(','))
return cls(x, y)
# 使用不同的类方法实例化对象
point1 = Point.from_tuple((3, 4))
print(point1.x, point1.y) # 输出:3 4
point2 = Point.from_string("5,6")
print(point2.x, point2.y) # 输出:5 6
|
2.2 @property与@xxx.setter#
- @property 将一个方法转换为属性调用,不需要加括号。
- @xxx.setter 可以限定修改范围
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
print("Hello")
return self._value
@value.setter
def value(self, new_value):
if new_value < 0: #限定条件
raise ValueError("Value cannot be negative")
self._value = new_value
test = MyClass(5)
test.value
# Hello
# 5
test.value = 100
test.value
# Hello
# 100
|
3. 类装饰器#
通过类装饰器,可以在实例化类对象时,自动地修改类的行为或属性。
3.1 示例用法#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def add_method(cls):
cls.new_method = lambda self: print("New method added!")
return cls
@add_method
class MyClass:
def original_method(self):
print("Original method")
obj = MyClass()
obj.original_method()
# Original method
obj.new_method()
# New method added!
|