命名空间和作用域

作用域,就是 python 程序中,可以直接访问命名空间的正文区域。

python 中程序的变量也是有作用范围的,在范围之外是不能访问的,能访问的范围决定于变量定义/赋值的位置。

局部作用域(Local,最内层,函数或闭包函数内,包含局部变量)

闭包函数外的作用域(Enclosing),主要就是嵌套函数中闭包函数外的区域,包含非局部(non-local)也非全局(non-global的变量)

全局作用域(glocal),当前程序的最外层区域,包含本程序文件/模块的全局变量

内建作用域(built-in)包含了内建函数、关键字等。在使用一个变量的时候,会按照由内而外的顺序取寻找该变量的定义,内层可屏蔽外层

num1=123   #全局作用域变量
def fun():
    num1=234  # 闭包函数外的函数中变量
    def fun1():
        num1=345  #局部作用域变量

python 中只有模块(module)、类(class)以及函数(def、lambda)能引入新的作用域

其他语句块是不会引入新的作用域的,如 if…else… 、try…except…和 for/while等

def fun():
    inner=21
    
list1=[1,2,3,4]
a='abcdef'
for i in list1:
    a+=a[i]
print(i)  #这里是可以使用i的,因为i在for中定义了,for不形成新作用域
print(a)

# print(inner)  #这里会报错,因为inner只在函数fun中定义了,在函数外没定义,所以找不到inner变量

global 和 nonlocal 关键字

global 用在局部作用域或闭包函数外的函数作用域中,用来指出在该作用域中使用的变量是全局变量,而非局部变量,该变量可以是在全局作用域中出现过的变量,也可以是没出现过的变量。
但是必须在第一次使用之前声明,否则就会报错

num = 0 # 这是一个全局变量
def fun1():
    num =2
    # global num # 函数内,在global声明之前已经使用过num.这里会报错
    print ("函数内: ", num)
    return num

fun1()
print ("函数外: ", num)

nonlocal 用在闭包函数内的函数作用域中,用来指出在该作用域中使用的同名变量不是局部变量,而是一个外部变量,注意,
若闭包函数外的函数中没有此同名变量则会报错

num = 0 # 这是一个全局变量
def fun1():
    # global num
    num = 1 # num 在这里是全局变量.
    def fun2():
        nonlocal num # 这里会报错,因为在外层函数中没有同名局部变量;注释掉global num就不会报错了
        num=2
        print("闭包函数内: ", num)
        return num
    fun2()
    print ("函数内: ", num)
    return num

fun1()
print ("函数外: ", num)

缘由

不可变类型

总的来说对于不可变类型:像 int 、 float 、 str 等类型;
定义即赋值,修改实际上是新的定义,这一类变量的定义和修改都是使用赋值运算符 '='。

可变类型

像 list 、 set 、 dict 等类型是一类可变类型,所谓可变类型,就是定义之后,还可以对变量进行修改,修改前后,
该变量的 id 不变,这一类变量定义使用赋值运算符,
修改则需要下标(或键),还可以有插入、删除等操作。

list1=['a','b','c']
def fun1():
    # global list1
    list1[0]='f'  #这里已经使用过全局变量了,在函数内就不能再定义同名的局部变量了
    print('fun1内,打算定义一个与全局变量同名的局部变量:')
    """
    若这一行没有注释掉#global list1就不会报错
    缘由是在同一个作用域中被定义了全局变量,此时是全局变量被赋值,修改
    """
    # list1=['s']  #这里定义同名的变量,会报错;   


def fun2():
    print('fun2内,打算定义一个与全局变量同名的局部变量:')
    list1=[123,'abc']   #这里定义了一个与全局变量同名的局部变量
    list1.append('123') #这里使用的也是局部变量
    print('fun2函数内:',list1)
fun1()
print('执行fun1之后,函数外:',list1)
fun2()
print('执行fun2之后,函数外:',list1)

参考Python细节之7、global与nonlocal的使用
之前也写过,但不详细global与nonlocal

posted @ 2021-08-04 18:38  索匣  阅读(138)  评论(0编辑  收藏  举报