zoukankan      html  css  js  c++  java
  • 函数命名空间和作用域

    三元运算:

    变量= 条件返回True的结果 if 条件 else 条件返回false的结果

    # a = 1
    # b = 5
    # c = a if a>b else b   #三元运算
    # print(c)
    结果显示: 5

     命名空间和作用域

    命名空间

    有三种

    #内置命名空间 —— python解释器
    # 就是python解释器一启动就可以使用的名字存储在内置命名空间中
    # 内置的名字在启动解释器的时候被加载进内存里
    #全局命名空间 —— 我们写的代码但不是函数中的代码
    # 是在程序从上到下被执行的过程中依次加载进内存的
    # 放置了我们设置的所有变量名和函数名
    #局部命名空间 —— 函数
    # 就是函数内部定义的名字
    # 当调用函数的时候 才会产生这个名称空间 随着函数执行的结束 这个命名空间就又消失了

    三种命名空间之间的加载与取值顺序:

    
    

    加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

    在正常情况下,直接使用内置的名字,当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字

    取值:

      在局部调用:局部命名空间->全局命名空间->内置命名空间

           在全局调用:全局命名空间->内置命名空间

    命名空间的查找顺序
    a) 如果在函数内调用一个变量,先在函数内(局部命名空间)查找,如果找到则停止查找。否则在函数外部(全局命名空间)查找,如果还是没找到,则查找内置命名空间。如果以上三个命名都未找到,则抛出NameError 的异常错误。
    b) 如果在函数外调用一个变量,则在函数外查找(全局命名空间,局部命名空间此时不可见),如果找到则停止查找,否则到内置命名空间中查找。如果两者都找不到,则抛出异常。只有当局部命名空间内,使用global 关键字声明了一个变量时,查找顺序则是 a) 的查找顺序。

    # def AddMoney():
    #     # 想改正代码就取消以下注释:
    #     global Money
    #   Money=0
    # Money = Money + 1 # AddMoney() # print (Money)
    
    
    作用域 

    作用域(包括函数的作用域链):

    小范围的可以用大范围的
    但是大范围的不能用小范围的
    范围从大到小(图)

    在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
    如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
    如果都没有,报错

    作用域两种
    全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域 ——globals()
    #globals 永远打印全局的名字
    # 对于不可变数据类型 在局部可以是查看全局作用域中的变量
    # 但是不能直接修改
    # 如果想要修改,需要在程序的一开始添加global声明
    # 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
     
    # a = 1
    # def func():
    #     global a
    #     a = 2
    
    # func()
    # print(a)
    此时结果显示:2 因为函数内声明了变量a=2 若将global a #注释掉,则print(a)=1

     
    局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——locals()
    #locals 输出什么 根据locals所在的位置
    #locals 返回一个名字/值对的字典。这个字典的键字是字符串形式的变量名字,字典的值是变量的实际值。
    # a = 1
    # b = 2
    # def func():
    #     x = 'aaa'
    #     y = 'bbb'
    #     print(locals())
    #     print(globals())
    # 
    # func()     
    # 此时locals是在局部作用域内,所以显示是{'y': 'bbb', 'x': 'aaa'}


    
    
    # a = 1
    # b = 2
    # def func():
    #     x = 'aaa'
    #     y = 'bbb'
    # print(locals())
    # print(globals())
    #
    # func()   
    # 此时locals是在全局作用域内,所以显示的是全局的名字
    
    

    函数的嵌套调用

    函数的调用:

    # def max(a,b):
    #     return a if a>b else b
    #
    # def the_max(x,y,z):  #函数的嵌套调用
    #     c = max(x,y)
    #     return max(c,z)
    #
    # print(the_max(1,2,3))   #打印结果    3   

    函数的嵌套:

    函数嵌套的定义:

    内部函数可以使用外部函数的变量。

    a = 1
    def outer():
        a = 1
        def inner():
            a = 2
            def inner2():
               # nonlocal a  #声明了一个上面第一层局部变量  a=2
                a = 1   #不可变数据类型的修改
                print('+',a)
            inner2()
            print('##a## : ', a)
        inner()
        print('**a** : ',a)
    
    outer()
    print('全局 :',a) 打印显示:     + 1
    ##a## : 2
    **a** : 1
    全局 : 1

    nonlocal只能用于局部变量,找上层离当前函数最近的局部变量。

    声明了nonlocal的内部函数的变量修改会影响到,离当前函数最近一层的局部变量。

    对全局无效,对局部也只是对最近一层有影响。

    函数名的本质:

      函数名就是一个变量,保存了函数所在的内存地址

    
    
    # # func()  #函数名就是内存地址
    # func2 = func  #函数名可以赋值
    # func2():

    # # l = [func,func2] #函数名可以作为容器类型的元素 # print(l) # for i in l: # i() # def func(): # print(123) # # def wahaha(f): # f() # return f #函数名可以作为函数的返回值 # # qqxing = wahaha(func) # 函数名可以作为函数的参数 # qqxing()
    
    
    
     

    闭包:

      内部函数包含对外部作用域而非全局作用域名字的引用,同时外部函数返回内部函数,该内部函数称为闭包函数

    x=1
    def f1():
    x=1000
    y=2
    def f2():
    y=9
    print(x)
    return y
    return f2 #这里返回的是函数f2

    f=f1()
    print(f) #得到的是一个函数值<function f1.<locals>.f2 at 0x0000000002875840>
    f() #此时调用他就可以使得f2内的print生效
    print(f())
    #打印返回值
    print(f.__closure__) #(<cell at 0x0000000002819558: int object at 0x0000000002885410>,)
    f.__closure__[0].cell_contents #1000

     闭包都有__closure__属性

    __closure__对象会返回闭包应用外围作用域的变量信息。f.__closure__保存外围作用域的变量内存地址,f.__closure__[0].cell_contents存放的是外围作用域的变量的值。

    对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。

     

    
    
     
  • 相关阅读:
    Ubuntu 14.04 配置iptables防火墙
    转 微软Sysinternals Suite工具13年12月版下载
    转详解Zoosk千万用户实时通信背后的开源技术
    Where is Silverlight now?
    A glance at C# vNext
    silverlight 进行本地串口调用的一种可行的解决方法 之silverlight端代码
    silverlight 进行本地串口调用的一种可行的解决方法
    silverlight 中javascript 代码与托管代码的互调用 以及一些思考
    使用cglib动态创建javabean
    数据库同步核心代码
  • 原文地址:https://www.cnblogs.com/liusouthern/p/8126965.html
Copyright © 2011-2022 走看看