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

    一,python的装饰器是什么?

    二,python装饰器

    三,带有参数的装饰器

    一,python的装饰器是什么?

    python装饰器其实就是一个函数,它用于给其他函数添加一些新功能。这个就是python的装饰器。

    二,python的装饰器

    1,python装饰器的原则

      a,不修改被装饰的函数的原代码

      b,不修改原函数的调用方式

    归纳一下其实就是装饰器对待被修饰的函数完全是透明,是感知不到装饰器的存在的。

    基于以上2点给被装饰的函数添加新功能。

    2,python装饰器的基本知识

    a,函数即变量

    b,高阶函数

    c,嵌套函数

    d,高阶函数+嵌套函数==》装饰器

    a,函数即变量

    a = 1 把内存比喻酒店的话,那么就会有间房存放1,然后存放1的房间门牌号就是a.
    b = a 这个其实就是给存放1的房间多添加一个门牌号。

    那么python是有垃圾回收的机制,那么怎样的情况下,才会回收1呢?
    只要存放1的房间号没有门牌号,即没有函数名,那么这个1就会立马被回收。如果人为的回收,可以使用del命令即可。


    那么函数和变量是一样的。比如
    def test():
    pass

    把test作为门牌号,函数体的内容放到房间里面

    当然,匿名函数也是一样的道理。如下图

     上面函数即变量的意思,其实就是你定义一个函数,其实当Python解释器执行到def 的时候并不会执行这个代码块,其实就是和存放变量一样,存放一下仅此而已。

    b,高阶函数

    高阶函数满足一下任一条件,即为高阶函数。

    1,把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码的情况下为其他添加新功能)
    2, 返回值中包含函数名(不修改函数的调用方式)

    def a():
        print('in the a')
    
    def b(a):
        pass
    
    b()
    

      像这种就算是高阶函数的一种,符合第一个条件。

    如果想要符合第二个条件,只要函数return a 就可以满足第二个条件了。

    c,函数的嵌套

    1,这个是函数的调用

    def test1():
        print('in the test1')
    
    
    def test2():
         test1()
    
    test2()
    

      



    2,这个是函数的嵌套

    def test1():
        def test2():
        print('in the test2')
    test1()
    

      

    d,高阶函数 + 嵌套函数 = 装饰器

    如下是个简单的装饰器:

    import time
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()
            stop_time = time.time()
            print('the func run time is {0}'.format(stop_time-start_time))
        return wrapper
    
    def bar():
        time.sleep(2)
        
        print('in the bar')
    
    
    
    bar = timmer(bar)
    

     

      可以发现,这个装饰是由高级函数和嵌套函数组成的。

    这个装饰器的功能就是给函数添加运行时间的功能。其实上面的bar = timmer(bar)可以使用python提供的语法糖来写那么就更简单了。

    import time
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()
            stop_time = time.time()
            print('the func run time is {0}'.format(stop_time-start_time))
        return wrapper
    
    @timmer
    def bar():
        time.sleep(2)
        print('in the bar')
    
    
    
    #bar = timmer(bar)
    

      

     这样一个装饰器就完成了。从这个简单的装饰器来看。我们可以发现当我们调用bar()这个函数的时候不仅仅是返回了函数的内容,而且还只能加了计算时间的功能。

    仔细一看 但我们调用bar()的时候,我们可以发现其实我们调用的是wrapper这个函数,因为timmer这个函数是return wrapper这个函数地址,所以bar = wrapper ,那么咱们调用的时候

    bar()其实就是等于wrapper()。

    上面的简单完成了装饰器的功能,如果想把这个装饰器用于其他函数,只需在其他函数上面添加@timmer即可装饰其他函数(前提其他函数是没有参数的)

    为了是上面的装饰器可以装饰其他函数,比如函数自带参数.所以咱们需要把上面的函数简单修改一下。

    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            func(*args,**kwargs)
            stop_time = time.time()
            print('the func run time is {0}'.format(stop_time-start_time))
        return wrapper
    
    @timmer
    def bar():
    print('in the bar') @timmer def test(name): print ('my name is {0}'.format(name)) bar() test()

      

      为了能够是装饰器可以装饰其他函数,将传入的参数设置成冗余。所以即使test有变量,也不会影响它的装饰的功能。

    上面讲到了bar = wrapper 同理 test=wrapper 所以如果test函数是需要传入参数的话,毫无疑问wrapper也是需要设置形参的。为了防止传入的参数不定,所以用*args和**kwargs来代替。当然这里传入的参数也需要使用*args和**kwargs

    还有一种就是要装饰的函数是带有return值的,所以装饰器要简单改一下,即装饰器里面接受一下赋值给一个变量,然后输出。

    import time
    def timmer(func):
        def wrapper():
            start_time = time.time()
            result = func()
            print(result)
            stop_time = time.time()
            print('the func run time is {0}'.format(stop_time-start_time))
        return wrapper
    
    @timmer
    def bar():
        time.sleep(2)
        print('in the bar')
        return 'from bar'
    
    bar()
    

      

    三,带有参数的装饰器

    #!/usr/bin/env python
    # -*- conding:utf-8 -*-
    import time
    user,passwd = 'test','test123'
    
    def auth(auth_type):
        def outer_wrapper(func):
            def wrapper(*args,**kwargs):
                username = input('username:').strip()
                password = input('password:').strip()
                if auth_type == 'local':
    
                    if user==username and passwd==password:
                        print('登录成功!')
                        res = func(*args,**kwargs)
                        return res
                    else:
                        print('登录失败')
                elif auth_type == 'ladp':
                    print('ladp正在建设中!')
            return wrapper
        return outer_wrapper
    
    
    
    
    def index():
        print('welcome to index page')
    
    
    @auth(auth_type='local') # a= auth(参数)  home = a(home)
    def home():
        print('welcome to home page')
        return 'from home'
    
    
    @auth(auth_type='ladp')
    def bbs():
        print('welcome to bbs page')
    
    
    
    
    
    index()
    print (home())
    bbs()
    

      

  • 相关阅读:
    分期付款购买固定资产账务处理
    会计要素计量
    接受现金捐赠分录
    分配股票股利的分录
    R语言代写对用电负荷时间序列数据进行K-medoids聚类建模和GAM回归
    R语言代写用随机森林和文本挖掘提高航空公司客户满意度
    R语言代写时间序列TAR阈值模型分析 2
    R语言代写时间序列TAR阈值模型分析
    R语言代写文本挖掘tf-idf,主题建模,情感分析,n-gram建模研究
    R语言代写文本挖掘NASA数据网络分析,tf-idf和主题建模
  • 原文地址:https://www.cnblogs.com/lin1/p/8386947.html
Copyright © 2011-2022 走看看