zoukankan      html  css  js  c++  java
  • 从本质上分析装饰器

    正规写法:

    import time
     
    def timeslong(func):
        def call():
            start = time.clock()
            print("It's time starting ! ")
            func()
            print("It's time ending ! ")
            end = time.clock()
            return "It's used : %s ." % (end - start)
        return call
    
    @timeslong
    def f():
        y = 0
        for i in range(10):
            y = y + i + 1
            print(y)
        return y
    
    print(f())

    等价写法:

    import time
     
    def timeslong(func):
        def call():
            start = time.clock()
            print("It's time starting ! ")
            func()
            print("It's time ending ! ")
            end = time.clock()
            return "It's used : %s ." % (end - start)
        return call
    
    
    def f():
        y = 0
        for i in range(10):
            y = y + i + 1
            print(y)
        return y
    
    f = timeslong(f)
    
    print(f())

    错误写法:

    import time
     
    def timeslong(func):
        start = time.clock()
        print("It's time starting ! ")
        func()
        print("It's time ending ! ")
        end = time.clock()
        return "It's used : %s ." % (end - start)
    
    @timeslong
    def f():
        y = 0
        for i in range(10):
            y = y + i + 1
            print(y)
        return y
    
    f()
    //-----------报错信息:
    Traceback (most recent call last):
      File "E:/python_pri/Fishc40.py", line 100, in <module>
        f()
    TypeError: 'str' object is not callable

    如果timeslong并不是一个返回函数便签的高阶函数,那么就会报这个错误!
    如果说f()的实现过程就是将f作为参数传入timeslong(),这样不应该报错,如:
    timeslong(f),这样不仅不报错,而且实现同样的功能!

       那,上面报错的原因是什么呢?我们得从本质上分析:
    @timeslong
    def f():
            pass
    上面这段代码等价于,下面这段代码:
    def f():
            pass
    f = timeslong(f)
            现在同名的f变量指向了新的函数,于是调用f()将执行新函数——timeslong(f)。
    那么,有鱼油就问了,既然f都赋了新的值,那么为什么timeslong(f)中的f调用的还是之前的f函数呢?

    这个问题问的好:
            原因是,f = timeslong(f)在执行的过程中,按照顺序先执行timeslong(f),再赋值f。在timeslong(f)这个过程中
    ,之前的f已经被保存到了timeslong函数的内部变量func中,当再次调用的f()的时候timeslong(f)中的是之前的f函数内容。
    所以确切的说: @timeslong 等价于 f = timeslong(func)。才更为准确。
            所以f()就等价于timeslong(func)()

    再来说报错问题,就很明显了,如果timeslong不是一个高阶函数,按照上面的写法,timeslong返回的是一个
    字符串,那么最终的结果可以看成:
    f = timeslong(f) = 'str'
    'str'()
    字符串当然不会被调用,所以报错:
    TypeError: 'str' object is not callable

  • 相关阅读:
    PowerDesigner数据模型(CDM—PDM)
    Eclipse解决JSP页面乱码问题
    mysql中Access denied for user 'root'@'localhost' (using password:YES)
    PS小技巧
    sublime使用心得
    Java的变量命名
    Java栈和堆的区别
    Mac 快捷键
    用shell脚本监控进程是否存在 不存在则启动的实例
    linux怎么运行.SH文件
  • 原文地址:https://www.cnblogs.com/douzi2/p/5580723.html
Copyright © 2011-2022 走看看