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. 示例
```
x=1
y=2
def f1():
        x=1
        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一样。

猜你喜欢

转载自www.cnblogs.com/yunweixiaoxuesheng/p/8962137.html