# 名称空间:正是存放名字x与1绑定关系的地方(x = 1)
# 定义:又名name space, 顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?
# 名称空间正是存放名字x与1绑定关系的地方
# 备注:python里面有很多名字空间,每个地方都有自己的名字空间,互不干扰,不同空间中的两个相同名字的变量之间没有任何联系。
# 名称空间有4种: LEGB
# L:locals:函数内部的名字空间,一般包括函数的局部变量以及形式参数
# E:enclosing function:在嵌套函数中外部函数的名字空间, 若fun2嵌套在fun1里,对fun2来说, fun1的名字空间就是enclosing.
# G:globals:当前的模块空间,模块就是一些py文件。也就是说,globals()类似全局变量。
# B:builtins: 内置模块空间,也就是内置变量或者内置函数的名字空间,print(dir(__builtins__))可查看包含的值。
# print(dir(__builtins__))
# __builtins__使用场景:模块的里面的使用
#备注: 不同变量的作用域不同就是由这个变量所在的名称空间决定的。
# 作用域即范围:经常使用的2种
# 全局范围:全局存活,全局有效
# 局部范围:临时存活,局部有效
# 查看作用域方法 globals(),locals()
# 作用域查找顺序
# 当程序引用某个变量的名字时,就会从当前名字空间开始搜索。搜索顺序规则便是: LEGB。即locals -> enclosing function -> globals -> builtins。
# 一层一层的查找,找到了之后,便停止搜索,如果最后没有找到,则抛出在NameError的异常。
# 例如:
# level = 'L0'
# n = 22
# def func():
# level = 'L1'
# n = 33
# print(locals()) # {'level': 'L1', 'n': 33}
# def outer():
# n = 44
# level = 'L2'
# print("outer:",locals(),n) #outer: {'level': 'L2', 'n': 44} 44
# def inner():
# level = 'L3'
# print("inner:",locals(),n) #此出打印的n是多少? inner: {'level': 'L3', 'n': 44} 44
# inner()
# outer()
# func()
# 备注:就是逐层向上查找,查找最近的值
# 闭包是个什么东西?
# 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。
# 当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
# 也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。
# 这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
# def outer():
# name = '小武哥'
# def inner():
# print("在inner里打印外层函数的变量",name)
# return inner # 注意这里只是返回inner的内存地址,并未执行
# f = outer()
# print(f) #inner at 0x01A8E810>
# f() # 相当于执行的是inner()
# # 以上程序解释了闭包:
# 1、有函数嵌套
# 2、内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数
# 3、跨一级可以仍然可以调用里面的内容,也就是,在最外层直接调用inner按道理不可以,但是进过return可以实现
# 4、嵌套函数里面需要有关键字return
# 以上代码执行原理:从outer进行运行开始,进入后见到return结束,返回嵌套函数inner的地址,直接inner加()直接运行嵌套里面的函数了
# 注意此时outer已经执行完毕,正常情况下outer里的内存都已经释放了,但此时由于闭包的存在,我们却还可以调用inner,
# 并且inner内部还调用了上一层outer里的name变量。这种粘粘糊糊的现象就是闭包。
# 闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
# 备注:闭包在哪会用? 装饰器就此产生了
# 函数嵌套:问题是 inner()在外部直接无法调用了,闭包搞定这个事情
# 1、有函数嵌套
# 2、内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数
# def outer():
# name = '小武哥'
# def inner():
# print("在inner里打印外层函数的变量",name)
# inner()
# outer()
# inner()# 外部无法调用内部的函数,这个使用直接报错