• 从本质上分析装饰器


    正规写法:

    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

  • 相关阅读:
    【android tools】内存、网络、界面性能响应优化的工具
    mysql命令(数据库备份与恢复)
    mysql中一些简单但是新手容易犯的错误
    Mysql bench执行sql语句批量操作数据所遇到的问题
    Excel “此单元格中的数字为文本格式,或者其前面有撇号” 设成数字格式
    VC程序异常中断的原因
    vs dump调试
    winsock.h与winsock2.h出现重定义或不同的链接
    QT中QString与string的转化,解决中文乱码问题
    线程中CreateEvent和SetEvent及WaitForSingleObject的用法
  • 原文地址:https://www.cnblogs.com/douzi2/p/5580723.html
Copyright © 2020-2023  润新知