变量作用域

python变量的作用域取决于变量被赋值的位置,python中,只有当变量在模块,类,函数中定义的时候才会有作用域的概念。一共有四种作用域: 局部作用域, 嵌套作用域, 全局作用域, 内置作用域

理解变量作用域是学习装饰器的关键之一,理解了作用域,也为理解更高级的语法与技术奠定基础。

1 变量的作用域

1.1 局部作用域

在函数中创建的变量,是局部变量,当函数被执行时,会创建一个局部作用域,这些局部变量只能在这个作用域内使用,出了这个作用域就无法使用了

def test():
    value = 100
    print(value)

print(value)

在函数外,就不能再访问value这个变量了,上面的代码执行时会报错

NameError: name 'value' is not defined

原因在于最后一行print语句是在全局作用域里执行的,但这个作用域里没有value这个变量。

1.2 嵌套作用域

def test():
    value = 100
    def test_2():
        value2 = 99
        print(value2, value)
    return test_2

a = test()
a()

如果一个函数的内部又定义了一个函数,那么这样就产生了嵌套作用域,其实嵌套作用域是一个相对概念。变量value存在于test函数所产生的局部作用域,变量value2存在于test_2函数所产生的局部作用域,value所在的作用域相对于value2来说就是一个嵌套作用域。

在函数test_2中可以访问test函数中的变量,但反过来就不行, 只允许向上访问。函数最后返回值是test_2,它是一个函数,赋值给a以后,a()就是在执行test_2函数

1.3 全局作用域

每个模块都是一个全局作用域,你也可以简单的理解为每个脚本就是一个全局作用域。在模块中创建的变量,这个模块里的任何地方都可以访问得到
示例1

value = 100

def test():
    print(value)

test()

在局部作用域里,你可以使用这个变量,但你不能修改这个变量的值
示例2

value = 100

def test():
    value = 99
    print(value)

test()
print(value)

程序的输出结果是

99
100

道理很简单,当你执行value = 99时,其实是在局部作用域里创建了一个变量value,这个value和全局的那个value根本就不是同一个变量。

那么为什么,在示例1中,就可以访问到全局的那个value呢,这是因为在搜索变量时是按照顺序进行的

局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域

python会按照这个顺序搜索变量,示例1中现在局部作用域搜索,没有找到后去全局作用域,这时找到了。

如果想在函数里修改全局变量,必须使用global关键字

value = 100

def test():
    global value
    value = 99
    print(value)

test()
print(value)

1.4 内置作用域

系统内固定模块里定义的变量,如预定义在builtin 模块内的变量

作用域所产生的诡异行为

a = 3
b = 5
sum = a + b
print(sum)

lst = [1, 2, 3]
print(sum(lst))

上面这段代码执行会报错

TypeError: 'int' object is not callable

这是一个非常诡异的错误,很多初学者都曾经遇到过,看代码,看不出有任何问题,可就是报了一个奇怪的错误。问题出在代码的第三行 sum = a + b。 sum 是一个变量,它的值等于a + b,sum这个变量存在于全局作用域里,最后一行的代码试图通过内置函数sum求列表里的元素之和,内置函数的作用域是内置作用域,python在搜索变量时是按照

  1. 局部作用域
  2. 嵌套作用域
  3. 全局作用域
  4. 内置作用域

的顺序进行的,最后一行代码想要使用内置函数sum,但是由于全局作用域里已经有了一个sum变量,就不会去内置作用域里继续寻找了。全局作用域里sum的值 a+b = 8,是一个int类型数据,int类型数据当然不是callable的。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案