python 面试题13 Python 作用域(scope) 和 LEGB

约束 名字空间 作用域 之间的那些事

不管在什么编程语言, 都有作用域这个概念.
作用域 控制在它范围内代码的生存周期, 包括名字和实体的绑定.
名字和实体的绑定, 我们可以理解成赋值. num = int_obj, 当我们执行这句代码时, 实际上我们已经得到一个(‘num’, int_obj)的关联关系, 我们也能将称之为约束, 这个约束也将存在名字空间(name space)里面, 名字空间也将是LEGB查找的依据.

而每个名字空间, 也将对应一个作用域, 作用域是代码正文中的一段代码区域, 作用域的有效范围更多是这段代码区域去衡量,一个作用域可以有多个名字空间, 一个名字空间也能有多个约束(多个赋值语句)

约束 和 作用域的关系

每个约束一旦创建, 将会持续的影响后面代码的执行, 但是约束也只能在名字空间内生效, 也就是说,一旦出了名字空间/作用域. 约束也将失效
这里写图片描述

在上面例子可以看到, 变量a在模块层和函数f层都有赋值, 在执行函数f时,输出6, 但是在下面却输出了3, 也就是因为函数f 中的 a=3 约束只有在函数f的作用域中生效,函数结束,a的值, 应该是最开始的a=3来控制, 我们现在应该隐约有种感觉, 为什么赋值语句会被称为约束?
我们完全可以理解成, 一个变量名, 可能有多次改变其绑定的实体对象的机会, 但是最终显示是哪个实体, 完全就是从作用域->名字空间->约束 来决定

变量名解析LEGB法则

以下探讨 变量查找的方式了?
python变量的作用域大概分为以下四类:
L(local) 局部作用域
E(Enclosing) 闭包函数外的函数中
G(Global) 全局作用域
B(Built-in) 内建作用域

搜索变量名的优先级:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域
LEGB法则: 当在函数中使用未确定的变量名时,Python会按照优先级依次搜索4个作用域,以此来确定该变量名的意义。首先搜索局部作用域(L),之后是上一层嵌套结构中def或lambda函数的嵌套作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到,则会出发NameError错误。

:上面的变量规则只适用于简单对象,当出现引用对象的属性时,则有另一套搜索规则:属性引用搜索一个或多个对象,而不是作用域,并且有可能涉及到所谓的”继承”
下面举一个实用LEGB法则的例子:

x = int(2.9)  # 内建作用域

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

在python中,模块(module),类(class)、函数(def、lambda)会产生新的作用域,其他代码块是不会产生作用域的,也就是说,类似条件判断(if…..else)、循环语句(for x in data)、异常捕捉(try…catch)等的变量是可以全局使用的

dataList = [1, 2, 3, 4]
for data in dataList:
    a = 1   #for循环中的变量a
    b = data + a

print(a) #在函数外也可视为全局变量使用

全局变量是指在函数外的变量,可以在程序全局使用,局部变量是指定义在函数内的变量,只能在函数内被声明使用

这里写图片描述

若内部作用域的想要修改外部作用域的变量,就要使用global关键字

a = 1
def demo():
    global a #globle关键字声明
    a = 123
    print(a)

demo()

print(a)

运行结果是
123
123
全局变量a的值被修改

nonlocal 关键字的使用方法和global关键字类似,修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()

运行结果为
100
100
闭包函数外的变量num值被修改

参考
http://python.jobbole.com/87280/
https://www.jianshu.com/p/17a9d8584530
https://blog.csdn.net/bylhjcsmmd/article/details/76372110
https://www.cnblogs.com/summer-cool/p/3884595.html
http://python.jobbole.com/88585/
拓展
http://python.jobbole.com/86465/
https://jingyan.baidu.com/article/6c67b1d6a09f9a2786bb1e4a.html

—–感谢各位大佬!

猜你喜欢

转载自blog.csdn.net/weixin_41853490/article/details/81267114