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

没看懂,前后逻辑关系

import time


def performance(f):

    def fn(*args, **kw):

        t1 = time.time()

        r = f(*args, **kw)

        t2 = time.time()

        print 'call %s() in %fs' % (f.__name__, (t2-t1))

        return r

    return fn

@performance

def factorial(n):

    return reduce(lambda x,y: x*y, range(1, n+1))

print factorial(10)

函数 factorial()与前面的performance()逻辑关系没看明白,哪位大侠指导一下


2020-01-17 403 浏览 2 回答

导入time 模块 

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

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

那就定义一个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
回复 7
@performance # factorial = performance(factorial)
在题目执行print factorial(10)过程中,首先是通过@performance,运行performance函数(此时用factorial函数作为参数,即f = factorial),
然后发现返回是fn,再运行fn函数,则运行闭包fn这个函数,其中ranhou yudao f(),则进行调用factorial函数即可
然后运行perfomance这个函数


2020-01-30
回复 2

举报

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