ExASIC
分享让工作更轻松

python的函数(二):作用域

我们在写函数时,时常需要引用全局的变量,或对全局变量赋值。又或者偶尔遇到局部变量与全局变量同名。在处理这些问题时,python语言的游戏规则是怎样的?今天我们就来学习这方面的内容。

什么是作用域?

在python语言里,在函数内部定义的变量,仅在函数内有效。在函数外面定义的变量对全局有效。我们把这种变量的有效范围叫作变量的作用域。

在python语言里,当引用变量时,会按照由内向外、由近及远的找查变量的定义及赋值。例如下面的代码:

a = 1
def func():
    b = a
c = a

当执行到b = a时, 第一步,会先在函数内部查找变量a。 第二步,如果第一步没有找到,会继续向外、向上查找。在这里就是查找函数外部,查找函数定义之前的代码,找到a = 1。(如果第一步查找到了a的定义,就忽略第二步。)

当执行到c = a时,向上跳过func(),直接找到a = 1。就是说会跳过同级的函数。也就是说,函数内的变量只对本函数有效,对外部没有影响。

三段代码对比

#示例一:函数内部
a = 1
def func_a ():
    a = 2
    def func_b ():
        a = 3        #<--
        print(a)
    func_b()
func_a()   #打印结果3

#示例二:向上一级
a = 1
def func_a ():
    a = 2            #<--
    def func_b ():
        print(a)
    func_b()
func_a()   #打印结果2

#示例三:全局
a = 1                #<--
def func_a ():
    def func_b ():
        print(a)
    func_b()
func_a()   #打印结果1

global和nonlocal是干什么的?

从上面的代码来看,python会自动按照由里向外、由近及远的规则查找变量。来看下面的几段代码。

#示例一:func_b不能修改func_a里的变量
a = 1
def func_a ():
    a = 2
    def func_b ():
        a = 3
    func_b()
    print(a)
func_a()  #打印结果仍然是2

#示例二:func_b修改了func_a里的变量
a = 1
def func_a ():
    a = 2
    def func_b ():
        nonlocal a   #<--
        a = 3
    func_b()
    print(a)
func_a()  #打印结果3

#示例三:func_b修改了全局变量,而不影响func_a内部的变量
a = 1
def func_a ():
    a = 2
    def func_b ():
        global a     #<--
        a = 3
    func_b()
    print(a)
func_a()  #打印结果仍然是2
print(a)    #打印结果3

所以,当需要修改外部变量的值时global和nonlocal是必需的。一般建议是不管是引用还是修改,都使用global和nonlocal

for循环没有单独的作用域

for内部定义的变量在循环结束后变量仍然有效。如:

for i in range(3):
    a = i
print(a)  #打印结果2

总结

简单总结一下变量作用域的规则:

  1. 由内向外、由近及远。
  2. 可直接引用外部变量、全局变量(建议使用nonlocal和global)。
  3. 当需要修改外部变量和全局变量时必需使用nonlocal和global来定义。
阅读数:
更多文章:文章目录
解惑专区
(支持markdown插入源代码)
欢迎使用ExASIC订阅服务
仅用于ExASIC最新文章通知,方便及时阅读。
友情链接: IC技术圈问答ReCclayCrazyFPGA