• @修饰符 二


    修饰符基础——闭包

    什么是闭包呢?标准的概念大家可以看wikipedia上的解释点击打开链接   举个例子:
    [python] view plain copy
    1. def do_add(base):  
    2.     def add(increase):  
    3.         return base + increase  
    4.     return add  

    do_add函数里嵌套了一个内层函数add,这个内层函数就是一个闭包,其实可以也不用管这个“闭包”的概念,先来看下这种模式解决些什么问题.

    调 用do_add函数:a = do_add(23),由于内层的函数add里的逻辑用到了do_add函数的入参,而这时这个入参base绑定了值23,由于do_add函数返回的是 函数add,所以这时的a其实就是内部的add绑定了23的函数add;同理可知,b = do_add(44),这里的b就是内部add绑定了44的函数add,a和b这两个add函数是不相同的,因为内部add绑定的值不同,只是两个函数的 模板相同罢了,这时我们执行a(100)得到结果是123,b(100)得到结果是144。这样做有什么用呢?其实可以这样看:我们可以把a = do_add(23)和b = do_add(44)看成是配置过程,23和44是配置信息,a(100)和b(100)根据不同的配置获得不同的结果,这样我们就可以解决开发中“根据 配置信息不同获得不同结果”的问题

    而修饰符实际上就是闭包一种形式,只是配置过程参数是所修饰的一个函数,并且用@符号代替了a=do_add(23)这样的配置方式,下面看一下修饰符的用法


    修饰符用法


    修饰符无参数,原函数无参数

    [python] view plain copy
    1. import time  
    2.    
    3. def timeit(func):  
    4.     def wrapper():  
    5.         start = time.clock()  
    6.         func()  
    7.         end =time.clock()  
    8.         print 'used:', end - start  
    9.     return wrapper  
    10.   
    11. @timeit  
    12. def foo():  
    13.     print 'in foo()'  
    14.    
    15. foo()  

    如上代码:对所修饰函数运行时间的进行统计,最后修饰过的 foo()  等价于 foo=timeit(foo) 而timeit返回wrapper,归根到底真正执行的是wrapper

    在实际应用中,函数很少没有参数,所以我们看看foo有参数的情况下,修饰符怎么用


    修饰符无参数,原函数有参数

    [python] view plain copy
    1. import time  
    2.    
    3. def timeit(func):  
    4.     def wrapper(args):  
    5.         start = time.clock()  
    6.         func(args)  
    7.         end =time.clock()  
    8.         print 'used:', end - start  
    9.     return wrapper  
    10.   
    11. @timeit  
    12. def foo(arg):  
    13.     print 'in foo(),arg is' + arg  
    14.     foo("aaaaa")  


    上述过程可以简化如下:

    [decorated] foo(‘aaaaa’)   =>   timeit(foo)(‘aaaaa’)  =>  wrapper(‘aaaaa’)  =>  [real] foo(‘aaaaa’)

    如果修饰符函数也有参数,又怎么用呢?


    修饰符有参数,原函数有参数

    [python] view plain copy
    1. import time  
    2.    
    3. def timeit(s):  
    4.   def wrapper1(func)  
    5.     def wrapper2(args):  
    6.         print "the decorator's arg is"+s  
    7.         start = time.clock()  
    8.         func(args)  
    9.         end =time.clock()  
    10.         print 'used:', end - start  
    11.     return wrapper2  
    12.   return wrapper1  
    13.  
    14. @timeit(s="hello")  
    15. def foo(arg):  
    16.     print 'in foo(),arg is' + arg  
    17. foo("aaaaa")  
    18.   
    19.   
    20. 同理,就是多加了一层闭包。  


    应用多个修饰符

    这个记住一个结论就好了,就是修饰符从离原函数最近的开始包裹,最外层的修饰符最后包裹

    应用举例——Fibonacci数列


    [python] view plain copy
    1. def memoize(f):  
    2.     cache = {}  
    3.     def helper(x):  
    4.         if x not in cache:              
    5.             cache[x] = f(x)  
    6.         return cache[x]  
    7.     return helper  
    8.  
    9. @memoize()  
    10. def fib(n):  
    11.     if n in (0, 1):  
    12.         return n  
    13.     else:  
    14.         return fib(n - 1) + fib(n - 2) 
  • 相关阅读:
    原型,构造函数,实例,__proto__
    To me
    那么再会吧!OI!(HNOI2019退役记)
    中山纪念中学培训杂题(难的都不在这里面qwq)
    关于菜鸡我
    树链剖分讲解
    [luogu] P4823 [TJOI2013]拯救小矮人(贪心)
    [luogu] P4551 最长异或路径(贪心)
    [luogu] P4364 [九省联考2018]IIIDX(贪心)
    [luogu] P4155 [SCOI2015]国旗计划(贪心)
  • 原文地址:https://www.cnblogs.com/ouyangping/p/8453042.html
Copyright © 2020-2023  润新知