装饰器示例

1. 装饰器语法糖示例

注解形式:

复制代码
# 1定义一个装饰器(装饰器的本质是闭包)
def check(fn):
    def inner():
        print("请先登陆")
        fn()

    return inner


# 2使用装饰器装饰函数(增加一个登陆功能)
# 解释器遇到@check 会立即执行 comment = check(comment)
@check
def comment():
    print("发表评论")


comment()
复制代码

真实面目:

复制代码
 1 # 1. 定义一个装饰器(装饰器的本质是闭包)
 2 def check(fn):
 3     def inner():
 4         print("登陆验证。。。")
 5         fn()
 6 
 7     return inner
 8 
 9 
10 # 需要被装饰的函数
11 def comment():
12     print("发表评论")
13 
14 
15 # 2. 使用装饰器装饰函数(增加一个登陆功能)
16 comment = check(comment)  # comment函数就是被装饰器装饰后的函数
17 
18 # 3. 执行装饰器函数
19 comment()
复制代码

输出结果:

1
2
登陆验证。。。
发表评论

  

一句话总结:利用闭包特点、不改变函数源码,为其执行前后添加功能。

2. 装饰有参数的函数

复制代码
 1 # 1. 定义装饰器
 2 def logging(fn):  # fn = sum_num,如果只有1个参数,此参数的实参必须是被修饰函数
 3     def inner(a, b):  # 内部函数的参数列表,必须直接或间接包含被装饰的参数列表
 4         print("被装饰函数执行之前")
 5         fn(a, b)
 6         print("被装饰函数执行之后")
 7 
 8     return inner  # sum_num = inner
 9 
10 
11 # 2. 使用装饰器装饰函数
12 @logging
13 def sum_num(a, b):
14     result = a + b
15     print(result)
16 
17 
18 # 3. 执行被装饰函数验证
19 sum_num(1, 2)  # 输出结果是3
复制代码

执行结果:

被装饰函数执行之前
3
被装饰函数执行之后

总结:

1. 装饰器就是闭包

2. 装饰器的外部函数的参数的实参必须是被装饰函数

3. 内部函数的参数直接或间接包含被装饰函数的列表

3. 装饰有返回值的函数

复制代码
 1 # 1. 定义装饰器
 2 def logging(fn):  # fn = sum_num,如果只有1个参数,此参数的实参必须是被修饰函数
 3     def inner(a, b):
 4         print("被装饰函数执行之前")
 5         result = fn(a, b)  # 内部函数的参数列表,必须直接或间接包含被装饰的参数列表
 6         print(f"被装饰函数执行之后,结果为:{result}")
 7         return result
 8 
 9     return inner  # sum_num = inner
10 
11 
12 # 2. 使用装饰器装饰函数
13 @logging
14 def sum_num(a, b):
15     result = a + b
16     return result
17 
18 
19 # 3. 执行被装饰函数验证
20 result = sum_num(1, 2)
21 print(result)
复制代码

执行结果:

1
2
3
被装饰函数执行之前
被装饰函数执行之后,结果为:3
3

  

总结:跟其他装饰器的使用,没有区别,要是有区别,就是内部函数必须有返回值,返回值为装饰函数的执行结果。

 4. 装饰带有不确定参数的函数

复制代码
 1 # 定义装饰器
 2 def logging(fn):  # fn = sum_num
 3     def inner(*args, **kwargs):
 4         print("被装饰函数执行之前")
 5         fn(*args, **kwargs)
 6         print("被装饰函数执行之后")
 7 
 8     return inner  # sum_num = inner
 9 
10 
11 # 使用装饰器装饰函数
12 @logging
13 def sum_num(*args, **kwargs):
14     print(args, kwargs)
15 
16 
17 sum_num(1, 2, 3, age="18")
复制代码

输出:

1
2
3
被装饰函数执行之前
(1, 2, 3) {'age': '18'}
被装饰函数执行之后

  

复制代码
 1 # 定义装饰器
 2 def logging(fn):  # fn = sum_num
 3     def inner(*args, **kwargs):
 4         print("被装饰函数执行之前")
 5         result = fn(*args, **kwargs)
 6         print("被装饰函数执行之后")
 7         return result
 8 
 9     return inner  # sum_num = inner
10 
11 # 使用装饰器装饰函数
12 @logging
13 def sum_num(*args, **kwargs):
14     print(args, kwargs)
15 
16 
17 sum_num(1, 2, 3, age="18")
复制代码

5. 多个装饰器装饰一个函数

复制代码
 1 # 定义装饰器1
 2 def check1(fn1):
 3     def inner1():
 4         print("登陆验证1")
 5         fn1()
 6 
 7     return inner1
 8 
 9 
10 # 定义装饰器2
11 def check2(fn2):
12     def inner2():
13         print("登陆验证2")
14         fn2()
15 
16     return inner2
17 
18 # 被装饰器的函数
19 
20 @check1
21 @check2
22 def comment():
23     print("发表评论")
24 
25 
26 comment()
复制代码

输出:

1
2
3
登陆验证1
登陆验证2
发表评论

  

6. 类装饰器

前提:需要掌握__init__、__call__ 2个内置函数。__init__函数用于类对象的初始化。当一个类的实例被像函数一样调用时,__call__ 方法会被调用。

1 # 定义一个类,实现__call__方法
2 class Check(object):
3     def __call__(self, *args, **kwargs):
4         print("我是call方法")
5 
6 c = Check()
7 c()

当执行到“对象()”即c()时,会自动咨询__call__方法。输出:我是call方法

 

动态行为修改:在特定条件下,可以通过动态修改 __call__ 方法来改变类的实例的行为。

复制代码
 1 class DynamicBehavior:
 2     def __call__(self, *args, **kwargs):
 3         if 'override' in kwargs:
 4             print("动态修改行为")
 5         else:
 6             print("默认行为")
 7 
 8 
 9 dyn = DynamicBehavior()
10 dyn()  # 输出:默认行为
11 dyn(override=True)  # 输出:动态修改行为
复制代码
1
2
默认行为
动态修改行为

  

类装饰器是一种特殊类型的装饰器,它使用类而不是函数来装饰其他函数或类。类装饰器可以通过定义 __call__ 方法来实现调用。

最佳实践:

  1. 创建一个类装饰器时,需要确保它的 __init__ 方法接受被装饰的函数或类作为参数。
  2. 在 __call__ 方法中实现装饰器逻辑,并返回一个新的函数或类。
  3. 使用 @ 符号将类装饰器应用到要装饰的对象上。
复制代码
 1 # 1. 定义类装饰器
 2 class MyDecorator:
 3     def __init__(self, decorated):  # 1. __init__必须有函数形参,实参是被装饰的函数
 4         self.decorated = decorated
 5 
 6     def __call__(self, *args, **kwargs):  # 2. 装饰逻辑写在__call__中
 7         # 在调用被装饰的函数之前执行一些操作
 8         print("Before function execution")
 9 
10         # 调用被装饰的函数
11         result = self.decorated(*args, **kwargs)
12 
13         # 在调用被装饰的函数之后执行一些操作
14         print("After function execution")
15 
16         return result  # 如果被修饰函数有返回值就用此句,如果没有,省略此句
17 
18 
19 @MyDecorator
20 def my_function():
21     print("Inside my_function")
22 
23 
24 my_function()
复制代码

输出结果:

1
2
3
Before function execution
Inside my_function
After function execution

  

 

posted @   Allen_Hao  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示