• 20201112 装饰器之函数即变量


     
    1-1-1
    def bar():
        print('in the bar')
    def foo():
        print('in the foo')
        bar()
    foo()
     
    
    1-1-2 如果把 bar 放在 foo 后面
    def foo():
        print('in the foo')
        bar()
    def bar():
        print('in the bar')
    foo()
    ---> 
    in the foo
    in the bar
    也能运行
     
    
    1-1-3 如果换一个位置调用
    def foo():
        print('in the foo')
        bar()
    foo()
    def bar():
        print('in the bar')
    这样结果会报错的
    --->
    in the foo
    Traceback (most recent call last):
      File "d:/VSCode/Untitled-2.py", line 5, in <module>
        foo()
      File "d:/VSCode/Untitled-2.py", line 3, in foo
        bar()
    NameError: name 'bar' is not defined
     
    
    这是为什么??
    变量的定义:大楼里有小房间,大楼里找一个房间,将 1 放入;x就是门牌号
    函数即变量
    def test():
        pass
    相当于,将 pass 代表的函数体,赋值给名字叫 test 的变量。
    变量直接调用,test需要通过 test()的方式调用。
    所以,函数在内存中是怎样存放的?
    在大楼中找一个小房子,把函数体放进房子,函数体就是 一堆字符串,将函数体房间的门牌号,叫做 test
     
    
    python 的回收机制是解释器,解释器是如何回收变量的?
    python解释器中,有一个概念叫 引用计数
    引用计数:x=1 现在内存中,把 x=1 这个值,实时存放;如果 y=x,实际上是把房间的门牌号又加上了一个 y
    引用计数,x代表一次引用,y代表一次引用;一共是 2 次引用。
    那么 python 什么时候 会 回收 1 呢?在 y 这个门牌号没了,x 这个门牌号 也没了的情况,就会清掉。也就是 没有门牌号了,就将 1 清掉。
    因为没人用了,就要 将房间里的东西,清出去,这就是 python 的回收机制。
     
    
    匿名函数
    有的函数是没有名字的,可以不定义名字——这就是匿名函数。
    calc = lambda x:x*3
    print(calc(3))
    ---> 9
    其实这就 相当于 一个函数了,除了变量之外,没有名字;后面为了调用,起了一个变量名 calc
    这个和定义的函数没有区别,只是没有名字而已。
     
    
    函数就是变量,匿名函数没有 def 没有声明函数名;那么它到底是如何存储的呢?
    lambda 定义的就是函数体,没有门牌号,就意味着,它会被回收。
    刚刚赋值了变量,calc;相当于给予了一个门牌号 calc
     
    
    总结:
    函数就是变量,定义一个函数就是相当于把函数体赋值给了函数名。
    变量有内存回收机制,函数也是一样的
     
    
    如果 x=1,所以永远不会被删除,del 就会被删除
    del 其实没有删掉内存地址的 1 ,只是把 x 的门牌号摘掉了,这个 1 定期刷新,发现没人引用了,才把它清掉
     
    
    现在回顾刚刚的 4 段代码:
    第 1 段代码:
    def foo():
        print('in the foo')
        bar()
    foo()
    会出错,因为调用 foo 时,运行到 bar()时,bar未定义
    会找一个房间放函数体,把
        print('in the foo')
        bar()
    放入
    然后给一个 门牌号 foo;函数体,在内存中就是一堆字符串,可以定义。
    但是在运行的时候,第一步 print 可以打印执行
    但是 bar();需要寻找带有 bar 门牌号的房间,但是没有,所以报错了
     
    
    第 2 段代码:
    在 foo 之上定义了函数 bar
    def bar():
        print('in the bar')
    def foo():
        print('in the foo')
        bar()
    foo()
    bar 在上面能够正常运行。
     
    
    第 3 段代码:
    将 bar 放到下面了,和上面是否有区别?
    def foo():
        print('in the foo')
        bar()
    def bar():
        print('in the bar')
    foo()
    为什么没有区别?
    如果有一个 x=1 变量;找一个屋子,将 1 放入;x就是门牌号
    又来一个 y=2 内存中会将 2 存入
    写入代码的方式 
    x=1
    y=2
    调用时,print(x,y)就ok
    如果 换一种方式, y=2   x=1     print(x,y) 运行结果一样的
    变量在使用的时候,实际上是分为两步的:
    第 1 步,是定义
    第 2 步,是调用
    python 是一种解释运行的语言,因为在调用之前,已经是被python 解释器,解释到的
    只要解释到,内存中就存在,存在就是可以用的。
     
    
    为什么第二段 和 第三段 代码 没有区别?
    第三段,先定义 foo; foo会把函数体当做一堆字符串放入内存当中,此刻 foo 是存在的
    然后继续定义 bar;将bar 的函数体 放入内存当中。
    此刻 bar 也是存在的了
    第三部调用,也是可以的
     
    
    先声明,后调用,只要调用之前存在了,就能调用到。
     
    
    第 4 段代码:
    def foo():
        print('in the foo')
        bar()
    foo()
    def bar():
        print('in the bar')
    为什么会报错?解释执行,解释器会先把 foo 指向 代码块,然后直接就执行了
    此刻,执行时,会发现,bar房间号,并没有对应到一个房间。是在下面才存在的,此刻并不存在。
    所以报错了,函数就是一种 “变量”。
  • 相关阅读:
    Sqoop
    Mediawiki
    TextMate 通用快捷键
    Wind7外接显示器选择拓展模式后,鼠标只能往右移动才能切换到外接显示器上,不能修改切换方向
    用Nginx+Lua(OpenResty)开发高性能Web应用
    netty4.0.x源码分析—bootstrap
    mysql分组合并GROUP_CONCAT
    Only POT texture can be compressed to PVRTC format
    手机屏幕左下角显示Fastboot mode是什么情况?
    判断UNITY版本号
  • 原文地址:https://www.cnblogs.com/azxsdcv/p/13964432.html
Copyright © 2020-2023  润新知