函数作用域
函数嵌套:在一个函数中定义了另外一个函数,函数有可见范围,这就是《作用域》的概念,内部函数不能再外部使用,不然会抛出NameError异常,因为外部不能看见内部变量 称为不可见
#嵌套函数举例:
def outer():
def inner():
print('inner') #打印inner
print('outer') #打印puter
inner() #执行了inner函数
outer() #调用outer
inner() #这里 会抛出NameError错误 因为inner再内部 外部不可见
作用域:一个标识符的可见范围,这就是标识符的作用域。一般常说的是变量的作用域
全局作用域:在整个程序的运行环境中都可见
局部作用域:在函数,类等内部可见,局部变量使用范围不能超过其所在的局部作用域
局部作用域举例:
def fn():
x = 11 #这就是局部作用域 在fn内
def fn1():
print(x) #这里的x是上一个函数的x 因为在他在自己的函数里面没有x只能往外找
print(x) # 这里打印x是报错的 因为全局没有x变量 它是看不见函数里面x的
从上面代码例子看出:外层变量作用域在内层作用域是可见的,内层定义的变量作用域外层是不可见的
全局变量global:使用global关键字的变量,将声明这个变量是全局的变量(x),函数内部可以直接使用全局变量(x) 如果全局也没有变量(x)就会报错
global总结:内部作用域使用x=5子类的赋值语句会重新定义局部作用域使用的变量x,但是一旦这个作用域中使用了global声明x为全局的,那么x=5相当于在为全局作用域的变量赋值
global使用原则:外部作用域变量会对内部作用域可见,但是不要在内部的局部作用域中直接使用,因为函数的目的就是为了封装,尽量与外界隔离,如果函数需要使用全局变量,请尽量使用函数的形参定义传实参的方式解决。尽量不用global。
举例:
x = 5
def foo():
global x #这里声明了x是全局的变量
x += 1 #这里可以进行修改
函数闭包 :
自由变量:未在本地作用域中定义的变量。例如定义在内层函数外的外层函数的做用域中的变量
自由变量举例:
def add():
c = [0] #这个就是自由变量 不会跟着外层函数消亡而消失 因为还有内存循环在使用
def foo():
c[0] += 1 #这里是对外层那个c的元素加1 而不是那个列表
return c[0]
return foo
add()
闭包:上面的代码就是闭包的概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包。很多语言都是这样概念,比如JavaScript
nonlocal关键字:使用了nonlocal关键字将变量标记为不在本地作用域定义,而在上一级的某个局部作用域中定义但不能在全局作用域中定义
nonlocal举例:
def counter():
count = 0
def inc():
nonlocal count #这里就是使用nonlocal标记count不是本地变量 去外面一层找
return count
return inc
foo = counter()
foo() #这里第一次执行 返回 1
foo() #执行一次会累加 这里第二次执行返回 2