为了账号安全,请及时绑定邮箱和手机立即绑定
关注
gadada

如何正确理解这三个return,个人理解在代码注释

import time
def performance(unit):
    def log_decorator(f):
        def fn(*args, **kw):
            t1=time.time()
            r=f(*args, **kw)
            t2=time.time()
            print 'call %s() in %f%s' % (f.__name__,t2-t1,unit)
            return r        # 返回f函数,即x*y?
        return fn      # 闭包?为了传参不受限制?
    return log_decorator   # 闭包?
    
@performance('ms')
def factorial(n):    
    return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)


2020-01-16 399 浏览 2 回答

然后开始定义我们的闭包函数,我之前不知道高阶函数,都叫闭包,这只是个名字不要纠结

首先闭包至少两层函数嵌套,这没问题

那就定义一个performance函数,

接下来返回值要是一个函数,那就写好return 一个函数,在开始定义里面函数

这一层内层函数一定要执行想要装饰的函数本身,否则就不叫装饰器了,而传进来的函数就是performance的参数f,

即f 就是@performance这句代码下面的函数 factorial,至于为什么是这个函数,那就是@语法的内部操作了.不用太纠结

所以在performance 和 fn这两个函数空间内,都可以执行额外的操作.闭包的作用就是为了不改动源代码 facorial 而进行额外操作.

你可以把 factorial(10)一步步分

factorial(10)

变成 factorial(10) = performance(factorial)(10)  // 可以理解吗?

由performance return 之后在变成  fn(10)  //因为只返回了fn函数 即return  而不是返回fn()的调用结果  

所以变成了fn(10) 即变成调用fn,参数是10

r = f(*args, **kw)

这一句调用f 就是调用最外层当初传进来的原始函数factorial

而里面的参数*args **kwargs 就是 fn(定义时的参数)

因为函数内部可以访问传进来的参数,这个好理解

*args **kwargs  这种参数定义就为了解决我也不知道装饰的函数有多少参数,反正全部接受在全部传递最保险

明白了吗?


再加一句

@performance

def factorial(n):

    //这里是函数源代码

这句装饰可以理解为

执行函数前自动执行了 performance(factorial)

完整拆开理解就是

执行一次函数调用factorial(10) 装饰后实际上执行 performance(factorial)(10) 即先吊用闭包函数

得到闭包内层函数之后在把原本参数10传递进内层函数,内层函数里面在调用原函数并且给参数10

就是不用直接调用,而是用函数来间接调用原函数

@装饰器的好处就是省略performance(factorial)(10)的手写过程.而且更好理解.只要用@装饰了,还是直接写原函数调用,逻辑简单

这是我二层的回答,三层也就是在@函数名 这句上再加个()传参调用罢了

2020-02-08
回复 3

个人拙见:

log_decorator(f) 这个是装饰器,它为了装饰 f 而存在,所以他有参数 f ,而在它内部有fn这个闭包,这个闭包是为了 传 f 的参数设置的,所以它的参数为 *args, **kw,在它内部,除了r = f(*args, **kw), 其他都是装饰,在装饰完以后,必然要返回所装饰的函数 f 即 return r.  顺着这个意义,外层自然要返回 fn,这里的fn就是r,顺着内层一层层返回,到这里,普通的无参装饰器就完事了,但这里装饰器也有参数,所以再套一层performance(unit),把装饰器参数传进去,最后再顺着上层返回log_decorator(也就是最内层的r)

总结一下,三层的装饰器函数分别有不同的存在的意义:传装饰器参数、传函数、传函数参数

而三层装饰器函数的返回值都是一个目的:返回原函数 f


2020-01-22
回复 2

sheeeeeeep

更正一下,,最内层返回的不是函数,而是这个原函数原本应该返回的结果(也就是说,装饰器只是加功能,原函数的返回值是不变的),在上面的例子中就是 10! 这个数 次内层也就是装饰器层它返回的才是一个函数(经过装饰的原函数),最外层是接着次内层再返回同一个函数
#1 2020-01-22 回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信