PythonPython
2025-10-29 08:56阅读:16评论:0
Python装饰器使用
@property装饰器 @property:它能把一个方法(需要调用的函数)变成属性(把函数直接当作属性来用) 没有使用@property之前 使用 @property 之后 @classmethod:它规定这个方法不是属于某个具体对象的,而是属于整个类的。通过类名直接调用 @staticmeth
_PROTECTED0_PROTECTED2_PROTECTED1__
1
2
3
4
5
6
7
8
9
10
11
12
13
class Circle: def __init__(self, radius): self.radius = radius def area(self): print(self.radius * self.radius * 3.14) circle = Circle(10)circle.area() # 需要加括号 # 输出314.0 _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Circle: def __init__(self, radius): self.radius = radius @property # 使用装饰器 def area(self): print(self.radius * self.radius * 3.14) circle = Circle(10)circle.area # 直接当属性用,不用加括号! # 输出314.0 _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ThirdGradeClass: total_students = 0 # 这是一个全班共有的变量 def __init__(self, name): self.name = name ThirdGradeClass.total_students += 1 # 每创建一个新学生,总数+1 @classmethod def get_total_students(cls): # 注意这里的参数是cls,代表“类”本身 return cls.total_students # 创建几个学生xiaoming = ThirdGradeClass("小明")xiaohong = ThirdGradeClass("小红") # 调用类方法,不需要通过某个具体的学生,通过类名就可以调用!print(ThirdGradeClass.get_total_students()) # 输出:2 # 通过某个学生对象也可以调用,但它知道的仍然是全班的信息print(xiaoming.get_total_students()) # 输出:2 _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ThirdGradeClass: @staticmethod def add_numbers(a, b): # 这个函数完全不知道班级、学生的存在 # 它只是一个实现特定功能的普通函数 return a + b # 使用这个静态方法,既可以通过类调用,也可以通过对象调用# 但它就是个计算工具,和班级、学生没关系xiaoming = ThirdGradeClass()result1 = ThirdGradeClass.add_numbers(5, 3) # 输出:8result2 = xiaoming.add_numbers(10, 2) # 输出:12 _PROTECTED0_PROTECTED2_PROTECTED1__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
## 单例装饰器(线程安全)# def singleton(cls): """实现线程安全的单例模式""" instances = {} lock = Lock() @wraps(cls) def wrapper(*args, **kwargs): with lock: if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 这是一个“记录魔法装备”(装饰器)def log_action(func): def wrapper(): print(f"记录:玩家进行了 {func.__name__} 操作!") # 自动获取函数名 func() # 执行原本的操作 return wrapper # 给函数穿上魔法装备!@log_actiondef build_house(): print("砰!砰!砰!一栋房子盖好了!") @log_actiondef mine_ore(): print("镐子咣咣咣,挖到了钻石!") # 现在直接调用,就会自动记录啦!build_house()mine_ore() - 带参数且有返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from functools import wraps def logger(func): @wraps(func) # 保留原函数元信息(如函数名、文档字符串) def wrapper(*args, **kwargs): print(f"调用函数:{func.__name__},参数:{args}, {kwargs}") return func(*args, **kwargs) # 传递参数并返回原函数结果 return wrapper @loggerdef add(a, b): return a + b print(add(2, b=3)) # 输出参数和结果 _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import time # “计时魔法装备”def timer(func): def wrapper(): start_time = time.time() # 开始计时 func() # 执行动作 end_time = time.time() # 结束计时 print(f"【{func.__name__}】动作耗时:{end_time - start_time:.2f} 秒") return wrapper # 给砍树函数穿上计时装备@timerdef chop_tree(): print("咔嚓...咔嚓...") time.sleep(2) # 假装砍树花了2秒钟 print("获得木头*5!") chop_tree() _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
player_level = 8 # 假设玩家现在8级 # “权限检查魔法装备”def check_level(required_level): def decorator(func): def wrapper(): if player_level >= required_level: func() # 等级足够,执行操作 else: print(f"权限不足!需要 {required_level} 级,你只有 {player_level} 级。") return wrapper return decorator # 使用末影箱需要10级,给它穿上检查装备!@check_level(required_level=10)def use_ender_chest(): print("成功打开末影箱,存取物品!") use_ender_chest() _PROTECTED0__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def deco1(func): print("装饰器1初始化") # 绑定阶段第二步:(绑定顺序自下而上) def wrapper1(): print("执行装饰器1逻辑") # 调用阶段第一步:(调用顺序自上而下) return func() # 调用内层装饰器的wrapper2 return wrapper1 def deco2(func): print("装饰器2初始化") # 绑定阶段第一步:(绑定顺序自下而上) def wrapper2(): print("执行装饰器2逻辑") # 调用阶段第二步:(调用顺序自上而下) return func() # 调用原始函数target return wrapper2 """谁在函数最上面谁优先执行"""@deco1 # 等价于 target = deco1(deco2(target))@deco2 # 先执行deco2(target),再将结果传给deco1def target(): print("执行目标函数") # 调用阶段第三步:(调用顺序自上而下) target() # 触发装饰器链的执行 _PROTECTED0_PROTECTED3_PROTECTED1_PROTECTED4_PROTECTED2__
1
2
3
4
5
6
7
8
9
10
11
12
13
from functools import wrapsimport time# “计时魔法装备”def run_timer(view_func): @wraps(view_func) # 关键1:用 @wraps(view_func) 保留原函数元数据(@action 添加的信息,如保留原函数的参数签名(self, request, ...)) def wrapper(self, request, *args, **kwargs): start_time = time.time() # 开始计时 response = view_func(self, request, *args, **kwargs) # 执行原函数方法并传递原函数的元数据,response为原函数的返回值 end_time = time.time() # 结束计时 print(f"【{view_func.__name__}】动作耗时:{end_time - start_time:.2f} 秒") return response return wrapper - 使用
1
2
3
4
5
6
7
8
@run_timer # 关键2:装饰器顺序:@action 在最内层(最下面),自定义装饰器在外侧,顺序不能乱@action(methods=['get'], detail=False, url_path='test', url_name='test')def test_api(self, request): return JsonResponse({ 'success': True, 'message': '测试接口正常', }) - ___PROTECTED_2__0___PROTECTED_3____PROTECTED_4__1___PROTECTED_5__object()、get_serializer() 等方法依赖视图实例 self,正确的参数签名能确保 self 被正确传递