—— 阿尔伯特·爱因斯坦

程序员の奇妙冒险

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) # 输出:8
result2 = 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_action
def build_house():
print("砰!砰!砰!一栋房子盖好了!")
 
@log_action
def 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
 
@logger
def 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
 
# 给砍树函数穿上计时装备
@timer
def 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),再将结果传给deco1
def target():
print("执行目标函数") # 调用阶段第三步:(调用顺序自上而下)
 
target() # 触发装饰器链的执行
 
_PROTECTED0_PROTECTED3_PROTECTED1_PROTECTED4_PROTECTED2__
1
2
3
4
5
6
7
8
9
10
11
12
13
from functools import wraps
import 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 被正确传递
评论(0)
暂无评论来抢沙发吧~

目录

SpringWonderland

探索 Spring 生态的奇妙世界

2025-10-29 08:56