变量作用域是一个很重要的概念,所谓变量作用域,就是你能访问到变量的范围,比如赋值给变量,从变量读取值。
如果对变量作用域理解错误的话,很有可能导致程序运行出现严重错误。
另外只有理解了变量作用域才能理解闭包函数的用法。
python变量作用域分为四个等级
- B(Built-in) - 内置作用域
- G(Global) - 全局作用域
- L(Local) - 局部作用域,顾名思义,只在一个局部小范围生效
- E(Enclosing) - 嵌套作用域, 比局部范围大一点
内置作用域B-Built-in
我们平时在使用代码时,print
, sum
, max
等等内置函数,都是在内置作用域内,只要解释器一直运行,这些内置函数或者变量就会一直有效,比如True
与False
,这两个是内置常量标识符,他们的值就是True
与False
,你不能对True
与False
赋值,只能获取值
内置作用域其实是通过把内置函数以及内置常量构建在一个叫builtins的模块中,这些内置作用域的变量可以在程序任何地方调用
全局作用域G-Global
全局的概念就是当前代码文件范围内,或者模块内的范围就是全局域,全局域变量在类内部,函数内部都可以获得值,但是不能修改值,一旦修改值,就是另外创建了一个新的局部变量
全局作用域示例
# 全局变量,不在任何的类,函数内部
name = "luxp"
# 可以在函数内部直接访问
def myfun():
print(name)
def myfun2():
print(name)
# 输出luxp,函数内部可以直接获得全局变量的值
myfun()
myfun2()
globals()函数
# 打印出所有全局变量
print(globals())
局部作用域L-Local
在python中,局部通常指类内部或者函数内部,以函数举例
# 在函数内部定义的变量只能在函数内部访问
def myfun():
num = 100
# num在函数内部可以任意访问
print(num)
myfun()
# 输出 100
# 这里属于函数外部,所以该条语句无法打印函数内部的num
print(num)
# 函数之间的变量是相互隔离的
def myfun1():
name = "python-xp.com"
print(name) #name在函数内部可以任意访问
def myfun2():
name = "luxp"
print(name) #name在函数内部可以任意访问
# myfun1与myfun2函数的name互不干扰,两个函数就好像一个个独立的房间一样
myfun1()
myfun2()
locals() - 局部变量收集器
def myfun():
a = 10
b = 20
print(locals())
myfun()
声明全局变量
# 在局部作用域范围内不能直接对全局变量重新赋值
name = "luxp"
def myfun():
# 尝试修改name的值
# 实际上定义了一个新的局部域
name = "python-xp.com"
print(name)
# 全局域的name
print(name)
# 输出 luxp
# 函数局部域的nanme
myfun()
# 输出 python-xp.com
从输出上可以看到,当myfun
内部对name
重新赋值后,只在内部生效,全局变量name
并没有变化,事实上是在myfun
内部创建了一个新的局部变量name
global-声明全局变量
如果想在函数内部修改全局变量,需要在函数内部使用global关键字声明变量
# 全局变量,不在任何的类,函数内部
name = "luxp"
def myfun():
global name
name = "python-xp.com"
print(name)
print(name)
myfun()
print(name)
# 输出
# luxp
# python-xp.com
# python-xp.com
使用global
后,就可以在函数内部对g全局变量进行修改了
嵌套作用域E-Enclosing
如果函数内部还有一个内部函数,情况就有些不同,下面这段代码,myfun2
称为myfun
的嵌套函数
# 对于嵌套函数myfun2来讲
# 外部函数myfun定义的变量可以访问到
# 但是myfun无法访问myfun2的变量,因为myfun2内部的变量只在myfun2内有效
# 相对的, myfun的作用域包含了myfun2
def myfun():
name = "luxp"
def myfun2():
print("myfun2内部:", name)
myfun2()
print("myfun:", name)
myfun()
# 输出两次 luxp
myfun2
是可以访问myfun
定义的变量,但是myfun2内部不能对myfun定义的变量进行修改
# myfun2
是可以访问myfun
定义的变量,但是myfun2内部不能对myfun定义的变量进行修改
def myfun():
name = "luxp"
def myfun2():
print(name)
# 添加了给name赋值语句,这时候name就变成了本地的变量,上面的print这一句产生未定义错误
name = "LUXP"
myfun2()
# 由于myfun2内部尝试修改非本地变量name报错
myfun()
执行报错:UnboundLocalError: local variable 'name' referenced before assignment
nonlocal - 声明非本地变量
在上例中如果要在myfun2
中修改myfun
的name值
,该怎么做呢?
必须声明它为nolocal
-非本地变量
def myfun():
name = "python-xp.com"
def myfun2():
# 添加了nolocal声明
nonlocal name
print("myfun2内部:", name)
name = "luxp"
print("myfun2内部:", name)
myfun2()
print("myfun:", name)
myfun()
# 输出:
# python-xp.com
# luxp
从输出上可以看到,使用nonlocal
声明后,myfun2
不仅可以获得name
的值,还可以对name
进行修改,此时name
的作用域就是嵌套作用域
讨论区