zoukankan      html  css  js  c++  java
  • Python学习之路6

    装饰器

    定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能。
    原则:1.不能修改被装饰的函数的源代码
       2.不能修改被装饰的函数的调用方式

    实现装饰器的知识储备:
      1.函数即“变量”
      2.高阶函数(满足下列条件之一就是高阶函数)

      • a:把一个函数名当作形参传给另一个函数(在不修改被装饰函数源代码的情况下修改其功能,但是调用方式变了)
      • b:返回值中包含函数名(不修改函数的调用方式,而修改函数功能)

      3.嵌套函数

    总结:

    高阶函数+嵌套函数=>装饰器


    1. 函数即变量

    def bar():  #这里定义个函数
    	print('this is bar...')
    
    func = bar  #将函数当变量一样赋值给func
    
    func()  #这是func加上()就可以当函数用了

      这就是函数即变量。

    2. 高阶函数

    a:把一个函数名当做形参传给另一函数(在不修改被装饰函数源代码的情况下修改其他功能,但是调用方式变了)

    def bar():
    	print('this is bar...')
    bar()
    print('----------------------------------')
    def test(func): #在这里增加了功能
    	print(func)
    test(bar)  #但是这里修改了调用方式

    b:返回值中包含函数名(不修改函数的调用方式,而修改函数功能)

    def bar():
    	print('this is bar...')
    bar()
    print('----------------------------------')
    def test(func):   #在这里增加了功能
    	print(func)
    	return func		#这里返回了函数地址
    bar = test(bar)   #将函数地址赋给一个变量,该变量和传入函数同名
    bar()		#这个变量加上括号,就可以当函数用了,同时又没有修改函数的调用方式
    

    3. 嵌套函数

    x = 1
    def test1():
    	def test2():
    		def test3():
    			x = 3
    			print(x)
    		test3()
    	test2()
    test1()
    

      像这样在一个函数里面定义一个函数就叫做嵌套函数。

    现在三个知识点都已经解释过了,下面先实现一个原始版的装饰器。

    原始版装饰器

    import time
    
    def test1():  #这里是被装饰的函数
        time.sleep(1)
        print("this is test1....")
    
    def timer(func):  #这里是装饰器函数
        def deco():
            strat = time.time()
            func()
            stop = time.time()
            print("run time %s" %(stop-strat))
        return deco
    
    test1 = timer(test1)
    
    test1()

      这个装饰器的功能是测试test1函数的运行时间,deco函数有这个功能,所以这里其实我想运行的是deco函数,timer()函数的返回值也就是deco函数的地址;同时deco函数想要运行也要满足另一个条件,那就是需要调用timer函数,只有当timer函数运行的时候timer函数里面写的那些东西才会生效或者说被激活,deco函数才会定义成功。到此,test=timer(test1)这句代码的意思就是,先调用timer函数让deco函数的定义生效,同时将要被装饰的函数test1函数的地址传入,让deco函数里面的func函数生效,这是timer函数又会将deco函数的地址返回,并将地址赋值给test1这个变量。然后下面的test1后面加上括号,变成test1()的形式,就可以运行了。这样一个原始版的装饰器就写完了。

    接下来要写一个真实装饰器的实例

    import time
    
    def timer(func):
        def deco():
            start_time = time.time()
            func()
            stop_time = time.time()
            print('the func run time is %s' %(stop_time-start_time))
        return deco
    
    @timer  #这里等于 test = timer(test),要装饰哪个函数,就在哪个函数前面加上这个
    def test():
        time.sleep(2)
        print('this is test...')
    
    test()

      上面这些都是一些比较基本的,如果装饰有参数的函数且参数的个数还都不一定怎么办呢?下面写一个高级案例 -- 有参数的装饰器

    高级案例 -- 有参数装饰器

    import time
    
    def timer(func):
        def deco(*args,**kwargs):  #在这里接收参数
            start_time = time.time()
            func(*args,**kwargs)
            stop_time = time.time()
            print('the func run time is %s' %(stop_time-start_time))
        return deco
    
    @timer
    def test(name):
        time.sleep(2)
        print('this is test...',name)
    
    test('vector')

      如果原test函数里面有返回值,被装饰后我们打印它print(test()),结果会是none。因为这时的test=deco,而deco没有返回值,所以打印不出来。这样就会出现一个问题,如果test函数有返回值,test函数的一个功能(返回值)就会被弄丢了。

    解决办法看下面案例。

    高高级案例 -- 有返回值的装饰器

    import time
    def timer(func):
        def deco(*args,**kwargs):
            start_time = time.time()
            res = func(*args,**kwargs)
            stop_time = time.time()
            print('the func run time is %s' %(stop_time-start_time))
            return res  #这里将func的返回值返回
        return deco
    
    @timer
    def test(name):
        time.sleep(2)
        print('this is test...',name)
        return 'asdfasdfgdfgd'
    
    print(test('vector'))

      这样就可以打印出返回值了。

    还有些时候我们需要给装饰器进行传参,给内部使用。解决方案看下面。

    高高高级案例 -- 给装饰器传参

    import time
    def timer(temp):
        print('this is ',temp)  #这里是加进来的参数
        def out(func):
            def deco(*args,**kwargs):
                start_time = time.time()
                res = func(*args,**kwargs)
                stop_time = time.time()
                print('the func run time is %s' %(stop_time-start_time))
                return res
            return deco
        return out
    
    @timer('temp')
    def test(name):
        time.sleep(2)
        print('this is test...',name)
        return 'asdfasdfgdfgd'
    
    print(test('vector'))
    

      实际上就是整体又在外面加了一层内嵌函数。

  • 相关阅读:
    LVS负载均衡原理详解和使用
    Linux---RPM和YUM
    【Codeforces】CF Round #676 (Div. 2)
    莫队学习笔记
    AtCoder Beginner Contest 187 题解
    【CodeForces】 Educational Codeforces Round 94
    【CodeForces】CF Round 649 (Div.2)
    【CodeForces】CF Round 648 (Div.2)
    【AtCoder】ABC 169
    【题解 LOJ2546「JSOI2018」潜入行动】
  • 原文地址:https://www.cnblogs.com/vector121/p/7874776.html
Copyright © 2011-2022 走看看