zoukankan      html  css  js  c++  java
  • Python笔记:装饰器

    装饰器

           1、特点:装饰器的作用就是为已存在的对象添加额外的功能,特点在于不用改变原先的代码即可扩展功能;

      2、使用:装饰器其实也是一个函数,加上@符号后放在另一个函数“头上”就实现了装饰的功能,执行被装饰的函数时,其实相当于func(*args, **kwargs) = decorator(func)(*args, **kwargs);

      3、基本原理:在加载装饰器时,也就是加载到@符时,会运行一次装饰器(也就是被@后的函数),它的返回值会替代被装饰的函数地址,而被装饰的函数的地址以装饰器函数参数的形式传进了装饰器。如下示例中:加载到@decorator时,运行了一次decorator()函数,这时函数hello()把函数名(也就是函数地址hello)作为装饰器参数func传了进去,decorator()执行完后返回函数inner()的函数地址,这个函数地址替代了函数hello()的函数地址,当执行hello('Jom')时,就会执行替换后的函数,即inner('Jom'),然后就会去执行inner()函数内的内容。

    简单装饰器示例:

     1 def decorator(func):
     2     print('hello python!')  # 相当于给hello添加的额外功能
     3     def inner(name):
     4         print('hello, my friend')  # 相当于给hello添加的额外功能
     5         func(name) # func即为hello()函数
     6 
     7     return inner
     8 
     9 @decorator # 装饰器用@表示,函数decorator()装饰函数hello()
    10 def hello(name):
    11     print('hello %s!' % name)
    12     
    13 hello('Jom') # 执行函数
    14 
    15 # 输出--------------------------------------------------------------
    16 # hello python!
    17 # hello, my friend
    18 # hello Jom!

      

    装饰器传参示例:

     1 def decorator_var(var1, var2):
     2     print('decorator_var')
     3 
     4     # 装饰器的传参,就是在简单装饰器外面再套一层“壳子”
     5     # 并且加载到装饰器的时候,会自动执行decorator_var和decorator两个函数
     6     def decorator(func):
     7         print('decorator')
     8 
     9         def inner(name):
    10             print(var1, var2)
    11             func(name)
    12 
    13         return inner
    14 
    15     return decorator
    16 
    17 
    18 @decorator_var('Python', '36')
    19 def hello(name):
    20     print('hello %s!' % name)
    21 
    22 
    23 hello('Jom')
    24 
    25 # 输出--------------------------------------------------
    26 # decorator_var
    27 # decorator
    28 # Python 36
    29 # hello Jom!

      4、安全防护:被装饰的函数的__name__属性(只测试了这个属性)会被修改为装饰器函数返回的函数名(虽然本质上已经不是在执行原函数了,因为它被装饰了,但是“表面上”我们代码还是执行的是这个函数,所以看起来就是原先的函数的属性被修改了,这样明显就是不安全的),但是为了防止这种不安全的行为,可以使用“from functools import wraps”来装饰器装饰器返回的函数。

     1 from functools import wraps
     2 
     3 
     4 # 装饰器__name__属性防护
     5 def decorator(func):
     6     @wraps(func)  # 这个装饰器可以防止被装饰的函数的__name__属性值被修改
     7     def inner(*args, **kwargs):  # 可以使用*args和**kwargs为“万能”的传参方式,当然这里也可以写成inner(a, b)
     8         func(*args, **kwargs)
     9 
    10     return inner
    11 
    12 
    13 # 加载到这个装饰器时,相当于:test_func = decorator(test_func),即test_func = inner
    14 # 如果没有对__name__的保护,加载装饰器后,如:函数test_func的__name__属性就会由“test_func”变为“inner”了
    15 @decorator
    16 def test_func(a, b):
    17     print('sum of a+b: %s' % (a + b))

      

  • 相关阅读:
    Navicat Premium 12安装及破解(四)
    ajax原理及应用(十六)
    为什么每次下载后必须关闭掉IO流(十五)
    FormData提交文件(十四)
    代理设计模式(三)
    单例模式(二)
    工厂模式(一)
    集采用的验证规则
    java泛型的理解
    spring中如何直接注入session和request对像
  • 原文地址:https://www.cnblogs.com/guyuyun/p/5771069.html
Copyright © 2011-2022 走看看