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

     1 def square_add(func):
     2     def new_function1(*args, **kwargs):
     3         result = func(*args, **kwargs)
     4         return result ** 2
     5     return new_function1
     6 
     7 def document_it(func):
     8     def new_function2(*args, **kwargs):
     9         print('Running function: ', func.__name__)
    10         print('Positional arguments: ', args)
    11         print('Keyword arguments: ', kwargs)
    12         result = func(*args, **kwargs)
    13         print('Result: ', result)
    14         return result
    15     return new_function2
    16 
    17 #一个函数可以拥有多个装饰器,且从距离该函数def最近的装饰器开始,依次向上执行
    18 
    19 @square_add
    20 @document_it
    21 def add_ints(a, b):
    22     return a + b

    add_ints函数本身是计算给定的两个int类型参数的和,但是,在此函数定义之前有“@装饰器名字”的表达式,意味着,该函数被其他函数装饰。所以,add_ints函数的调用结果就不只是求和了。一个函数可以拥有多个装饰器,且从距离该函数def最近的装饰器开始,依次向上执行。装饰器document_it距离被装饰的函数add_ints最近,因此,优先执行该装饰器。当add_ints函数被调用时,即本例中“add_ints(3,5)”,实际执行的过程如下:


    1.调用函数document_it(add_ints),我们发现document_it本身是返回了new_function2,调用端用一个名叫add_ints的函数来接收这个new_function2的返回值;

    注意:add_ints已经不是那个只求和的函数了

    2.add_ints函数实际上现在指向的是new_function2,因为new_function2这个函数(是document_it的内部函数)可以有任意多个位置参数或关键字参数,所以,我们可以通过“add_ints(3,5)”这样的方式,来给new_function2传入一组位置参数(以元组的形式将3、5传入);

    3.执行new_function2的函数体,很明显,print('Running function: ', func.__name__),这条语句中func是指add_ints;args位置参数是一个元祖(3,5);kwargs关键字参数没有传入参数,所以是空字典;接下来是这条语句“result = func(*args, **kwargs)”,我们已经知道func实际是指add_ints,那么func(*args, **kwargs)就相当于add_ints(3,5),因此,result的值就是add_ints(3,5)的返回值,即8;紧接着print打印result的值:8;最后返回result的值8;到这一步,document_it这个装饰器已经执行完毕,接下来就是执行下一个装饰器square_add。

    4.执行square_add(func),此时,func是指?由上面的分析,我们可知,被document_it装饰后的add_ints函数,实际上是指new_function2,所以,在执行square_add(func)时,func就是指的new_function2。为了证明这一点,我们可以在square_add这个函数中加一句print(func):


    5.由第4步可知,程序实际上是执行square_add(new_function2),而square_add函数是返回new_function1函数,同样用名字叫做add_ints的变量来接收这个函数,也就是说,此时add_ints实际上是指向new_function1:



    6.执行add_ints(3,5)就相当于new_function1(3,5),即执行的是new_function1的函数体,此时new_function1的参数是位置参数元组(3,5)。由于此时的func是指new_function2,所以,result = func(*args, **kwargs)就相当于将new_function2(3,5)的返回值赋值给result,我们已经明白new_function2(3,5)恰好是装饰器document_it的返回值8,因此,result = 8;接下来,返回8的平方,即64.


    综上所述,最终的执行结果是:
    >>> add_ints(3, 5)
    Running function:  add_ints
    Positional arguments:  (3, 5)
    Keyword arguments:  {}
    Result:  8
    64
    >>>

  • 相关阅读:
    matplotlib 进阶之origin and extent in imshow
    Momentum and NAG
    matplotlib 进阶之Tight Layout guide
    matplotlib 进阶之Constrained Layout Guide
    matplotlib 进阶之Customizing Figure Layouts Using GridSpec and Other Functions
    matplotlb 进阶之Styling with cycler
    matplotlib 进阶之Legend guide
    Django Admin Cookbook-10如何启用对计算字段的过滤
    Django Admin Cookbook-9如何启用对计算字段的排序
    Django Admin Cookbook-8如何在Django admin中优化查询
  • 原文地址:https://www.cnblogs.com/paomaliuju/p/5073273.html
Copyright © 2011-2022 走看看