Python名称空间与闭包

一、 名称空间(namespace)
1. 名称空间的分类
Python中通过提供 namespace 来实现重名函数/方法、变量等信息的识别,其一共有三种 namespace,分别为:、
    - local namespace: 作用范围为当前函数或者类方法
    - global namespace: 作用范围为当前模块
    - build-in namespace: 作用范围为所有模块

2. 名称空间的查找顺序
    1. local namespace
    2. global namespace
    3. build-in namespace

3. 作用域
全局作用域:内置名称空间,全局名称空间
局部作用:局部名称空间
全局作用域的变量:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕
局部作用域的变量:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效

x=1000
def func(y):
        x=2
        print(locals())                #    {'x': 2, 'y': 1}    局部命名空间变量,作用于就在本函数内
        print(globals())              
        #    全局名称空间变量:{'__package__': None, 'x': 1000, '__file__': '...', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x008059B0>, '__doc__': None, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x0136D7C8>, '__spec__': None, '__cached__': None}

func(1)
print(locals())
print(globals())
print(globals() is locals())    #    True
locals 在函数外的全局空间中所以和globals()内容一致

二、 闭包(closure)
1. 创建闭包
在Python中创建一个闭包可以归结为以下三点:
    - 闭包函数必须有内嵌函数
    - 内嵌函数需要引用上一级函数namespace中的变量
    - 闭包函数必须返回内嵌函数


2. 示例

形成闭包之后,闭包函数会获得一个非空的__closure__属性

__closure__属性是一个元祖,元组里面的对象为cell对象,而访问cell对象的cell_contents属性则可以得到闭包变量的当前值

x=1
y=2
def f1():
  x=4
  def f2():
    print(x,y)
  return f2
f
=f1() print(dir(f))               # 从结果看出f对象中包含__closure__属性 print(f.__closure__)           # __closure__对应的元祖中,包含cell类型的对象 print(f.__closure__[0])         # cell类型的对象 print(f.__closure__[0].cell_contents) # cell的值 ----------------------------------------------------------------------------------- 结果: 4 2 ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] (<cell at 0x014659D0: int object at 0x1D468A00>,) <cell at 0x014659D0: int object at 0x1D468A00> 4


3. 结论
闭包的原理,当内嵌函数引用了包含它的函数(enclosing function)中的变量后,这些变量会被保存在enclosing function的__closure__属性中,成为enclosing function本身的一部分;也就是说,这些变量的生命周期会和enclosing function一样。

原文地址:https://www.cnblogs.com/yunweixiaoxuesheng/p/8962137.html