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

    在学习函数装饰器前,首先要学习高阶函数+函数嵌套+闭包

    •  高阶函数

    只要满足下列条件之一就是一个高阶函数:

    1.函数接收的参数是一个函数名

    2.函数的返回值是一个函数名

    第一种情况:接收的参数是一个函数名

    1 def foo1(name):
    2     return name()
    3 def foo2():
    4     print('this is foo2')
    5 
    6 foo1(foo2)
    运行结果:
    ##this is foo2

    第二种情况:返回值是一个函数名

    def foo1():
        return 'this is foo1'
    
    def foo2():
        print('this is foo2')
        return foo1
    
    func = foo2()
    print(func)
    print(func())

    运行结果:

    # this is foo2
    # <function foo1 at 0x000000000216E378>
    # this is foo1
    • 函数嵌套

    什么是函数嵌套?

    在一个函数里嵌套一个子函数就是一个函数嵌套。

    def father(name):
        def son():
            print('这个名字是:%s'%name)
            def grandson():
                name = '我自己'
                print('这个名字是 :%s'%name)
            grandson()
        son()
    father('weibo')

    运行结果:

    1 # 这个名字是:weibo
    2 # 这个名字是 :我自己
    • 闭包

    概念:实质上就是一个函数嵌套,而闭包指的是函数作用域(作用的变量)

    装饰器

    什么是装饰器呢?

    装饰器本质上就是一个函数,功能就是在不改变原有函数以及原有函数的调用方式的基础上为原有函数添加新功能

    装饰器:高阶函数+函数嵌套+闭包

    原则:

    1,不改变被修饰函数的源代码

    2,不改变被修饰函数的调用方式

    一个简单的装饰器架子:

    
    
    ##  一个简单的装饰器架子
    ## 需求:在不改变test源代码和调用方式的前提下为test函数添加一个计时的功能
    import time

    def
    decorator_func(func): def functor(): time_start = time.time() func() time_end = time.time() print('运行test函数所用的时间是:%s'%(time_end-time_start)) return functor @decorator_func ## 语法塘:相当于 test = decorator_func(test) def test(): time.sleep(3)
       print('test函数')
    return '这是test的内容' res = test() ## res = decorator_func(test)()-->functor() print(res)

    运行结果:

    1 # test函数
    2 # 运行test函数所用的时间是:3.000171422958374 3 # None

    上述的test()函数不能带有返回值,因为在装饰器函数中没有接收到,下面接收这个return值

     1 import time
     2 
     3 def decorator_func(func):
     4     def functor():
     5         time_start = time.time()
     6         test1 = func()      ##  这里就是将func()运行,并把return的值赋值给test1
     7         time_end = time.time()
     8         print('运行test函数所用的时间是:%s'%(time_end-time_start))
     9         return test1
    10     return functor
    11 
    12 @decorator_func     ##  语法塘:相当于 test = decorator_func(test)
    13 def test():
    14     time.sleep(3)
    15     return '这是test内容的'
    16 
    17 res = test()        ##  res = decorator_func(test)()-->functor()
    18 print(res)

    运行结果:

    1 # test函数
    2 # 运行test函数所用的时间是:3.000171661376953
    3 # 这是test内容的

    被修饰函数加入参数:

     1 import time
     2 
     3 def decorator_func(func):
     4     def functor(*args,**kwargs):        ## 这里加入参数
     5         time_start = time.time()
     6         test1 = func(*args,**kwargs)      ##  这里就是将func()运行,并把return的值赋值给test1
     7         time_end = time.time()
     8         print('运行test函数所用的时间是:%s'%(time_end-time_start))
     9         return test1
    10     return functor
    11 
    12 @decorator_func     ##  语法塘:相当于 test = decorator_func(test)
    13 def test(a,b,c):
    14     time.sleep(3)
    15     print('test函数')
    16     print('打印出%s中的%s中的%s'%(a,b,c))
    17     return '这是test内容的'
    18 
    19 res = test('test1','test2','test3')        ##  res = decorator_func(test)()-->functor()
    20 print(res)    

    运行结果:

    1 # test函数
    2 # 打印出test1中的test2中的test3
    3 # 运行test函数所用的时间是:3.000171422958374
    4 # 这是test内容的
    • 注意:

    被装饰器函数修饰过的函数本质上已经是另一个函数了,实际开发中有时候会给我们带来困扰,所以可以加@wraps修饰,将函数名转为原来的函数名,消除这种影响。

    例子:

    import time
    from functools import wraps
    def decorator_func(func): @wraps def functor(*args,**kwargs): ## 这里加入参数 time_start = time.time() test1 = func(*args,**kwargs) ## 这里就是将func()运行,并把return的值赋值给test1 time_end = time.time() print('运行test函数所用的时间是:%s'%(time_end-time_start)) return test1 return functor @decorator_func ## 语法塘:相当于 test = decorator_func(test) def test(a,b,c): time.sleep(3) print('test函数') print('打印出%s中的%s中的%s'%(a,b,c)) return '这是test内容的' res = test('test1','test2','test3') ## res = decorator_func(test)()-->functor() print(res)

    扩展:多个装饰器一起用:

     1 import time
     2 
     3 def decorator_func1(func):
     4     def functor(*args,**kwargs):
     5         print('开始运行装饰器1')
     6         time_start = time.time()
     7         test1 = func(*args,**kwargs)      
     8         time_end = time.time()
     9         print('运行test函数所用的时间是:%s'%(time_end-time_start))
    10         print('停止运行装饰器1')
    11         return test1
    12     return functor
    13 
    14 def decorator_func2(func):
    15     def functor(*args,**kwargs):
    16         print('开始运行装饰器2')
    17         res = func(*args,**kwargs)
    18         print('装饰器2运行结束')
    19         return res
    20     return functor
    21 
    22 @decorator_func1     
    23 @decorator_func2        ##  这里的语法塘相当于: res = decorator_func1(decorator_func2(test('test1','test2','test3')))
    24 def test(a,b,c):
    25     time.sleep(3)
    26     print('test函数')
    27     print('打印出%s中的%s中的%s'%(a,b,c))
    28     return '这是test内容的'
    29 
    30 res = test('test1','test2','test3')        
    31 print(res)

     运行结果:

    1 # 开始运行装饰器1
    2 # 开始运行装饰器2
    3 # test函数
    4 # 打印出test1中的test2中的test3
    5 # 装饰器2运行结束
    6 # 运行test函数所用的时间是:3.000171661376953
    7 # 停止运行装饰器1
    8 # 这是test内容的

    Python内置装饰器

    在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

    • staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
    • classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
    • property 是属性的意思,表示可以通过通过类实例直接访问的信息
  • 相关阅读:
    adb root : adbd cannot run as root in production builds
    通过adb shell操作android真机的SQLite数据库
    基金--智能定投
    使用注册表优化终端、编辑器的中英字体混合显示,如「Consolas + 雅黑」「Monaco + 雅黑」
    诗词中的雨
    最好的PHP博客系统
    [重要更新][Quartus II][14.1正式版]
    解决Xilinx ISE在Win8下打开崩溃闪退的方法
    THE CUSTOMISER
    RAD Studio 2010~XE8 官方 ISO 下载地址 (2015-03-28更新)
  • 原文地址:https://www.cnblogs.com/maoxinjueluo/p/12581062.html
Copyright © 2011-2022 走看看