[Python] Python中的变量作用域

本文介绍了Python中的变量作用域,包括Local(局部)、Enclosed(嵌套)、Global(全局)和Built-in(内置)四种情况,并详细阐述了变量查找顺序(LEGB规则)。文章还讨论了如何使用global和nonlocal关键字来修改不同作用域的变量,强调了在不同作用域内变量的创建和访问规则。

问题:简述以下Python中的变量作用域(变量查找顺序)


变量的作用域:变量的有效使用范围

变量的作用域由变量的定义位置决定 

Python变量作用域分4种情况:

L:Local,局部作用域,即在函数中定义的变量;

E:Enclosed,嵌套作用域,可理解为嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;

G:Global,全局作用域,就是一般模块文件顶层声明的变量具有全局作用域;

B:Built-in,内置作用域,是预先定义好的,在__builtins__模块中,可理解为是一些内置的函数名、异常等关键字

x = int(2.9)  #  int  built-in
 
g_count = 0   # global
def outer():
     o_count = 1   # enclosed
     def inner():
         i_count = 2   # local

python中变量的使用遵循LEGB规则

创建变量时从上往下创建

搜索变量时从下往上搜索,局部作用域(Local) > 嵌套的父级函数的局部作用域(Enclosed) > 当前模块中的全局作用域(Global) > python内置作用域(Built-in)

在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误

在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域

if True:
     x =  1
     
print(x)  # 1
def test():
     x =  2
     
print(x)  # NameError: name 'x' is not defined

1.变量作用域

1.1 Local

Local:局部作用域

局部变量定义在函数内部,它的作用域也仅限于函数内部,只有在函数运行时,局部变量才会被创建,当函数执行完毕后,内部定义的变量会被销毁并回收

# 局部作用域
def fun():
    loc_var = 2
    print(loc_var)#输出2
    
fun()  # 2

# 报错
print(loc_var)  # NameError: name 'loc_var' is not defined

1.2 Enclosed

Enclosed:嵌套作用域,一般是在函数中嵌套函数的时候,外层函数的变量作用域 

# Enclosed(嵌套)作用域
def fun1():
    num = 2
    print("这是fun1打印的:", num)
    def fun2():
        print("这是fun2打印的:", num)
    return fun2

# 调用fun1
temp = fun1()  # 这是fun1打印的: 2

# 调用fun2
temp()  # 这是fun2打印的: 2

在这里函数fun2里面并没有定义变量num,但是它能够引用外层函数fun1定义的num变量,此时变量num的作用域就是Enclosed 

1.3 Global

Global:全局作用域

一般模块文件顶层声明的变量具有全局作用域,从外部来看,模块的全局变量就是一个模块对象的属性,仅限于单个模块文件中

全局变量的作用域是整个程序,变量既可在函数内使用,也可以在函数外使用

# Global(全局)作用域
num = 2
def fun():
    print("这是fun打印的:", num)

fun()  # 这是fun打印的: 2
print(num)  # 2

1.4 Built-in

Built-in:内置作用域

Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等

# 导入builtins模块,搜索内置作用域
# 一般来说无需手动导入builtins模块,不过可以看看这个模块中包含了哪些内置变量
import builtins
dir(builtins)

导入builtins模块会让内置作用域内的变量直接置于当前文件的全局范围,自动搜索内置作用域则是最后的阶段进行搜索 

2.变量的使用规则

python中变量的使用遵循LEGB规则

① 创建变量时从上往下创建,搜索变量时从下往上搜索 

② 创建变量时,下层变量会覆盖上层同名变量,但不会改变上层变量的值,除非使用 gloablenonlocal 关键字声明

3.变量的修改

当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字

3.1 global关键字修改全局变量

一般全局变量一经定义后几乎是不用改的,也不允许在局部修改全局变量,除非使用global关键字声明 

num = 1
def fun():
    # 修改全局变量
    num += 1
    print(num)
    
fun()  # UnboundLocalError: local variable 'num' referenced before assignment

可以看到,当我们试图在函数fun创建的局部作用域内改变全局变量num就会报错,但如果在修改之前使用global关键字声明时,就会正常修改外部的全局变量num

num = 1
def fun():
    # 使用global声明
    global num  
    # 修改全局变量
    num += 1
    print(num)

# fun函数修改前
print(num)  # 1

fun()       # 2

# fun函数修改后
print(num)  # 2

3.2 nonlocal关键字修改外层函数变量 

在函数中嵌套函数时,嵌套在里面的函数创建的作用域内一般也是不允许改变外层函数变量的值的,除非是nonlocal关键字声明

# 不使用nonocal声明,修改外层函数变量值
def fun1():
    num = 1
    print(num)  # 修改前
    def fun2():
        num += 1
        print(num)  # 修改后
    return fun2

# 调用fun1
temp = fun1()  # 1

# 调用fun2
temp()  # UnboundLocalError: local variable 'num' referenced before assignment

可以看到,报错和在函数内不使用global关键字修改全局变量报的错是一样的,当使用nonlocal关键字声明后再修改就不会报错了 

# 使用nonocal声明,修改外层函数变量值
def fun1():
    num = 1
    print(num)  # 修改前
    def fun2():
        # 使用nonlocal声明
        nonlocal num  
        num += 1
        print(num)  # 修改后
    return fun2

# 调用fun1
temp = fun1()  # 1

# 调用fun2
temp()  # 2
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值