命名空间、全局/局部做用域、做用域链、闭包

命名空间:3种python

内置命名空间 —— python解释器
  就是python解释器一启动就能够使用的名字(input、print ...)存储在内置命名空间中
  内置的名字在启动解释器的时候被加载进内存里安全

全局命名空间 —— 咱们写的代码但不是函数中的代码
  是在程序从上到下被执行的过程当中依次加载进内存的
  放置了咱们设置的全部变量名和函数名闭包

局部命名空间 —— 函数内写的代码
  就是函数内部定义的名字
  当调用函数的时候,才会产生命名空间,随着函数执行的结束,这个命名空间就又消失了函数

在局部:能够使用全局、内置命名空间中的名字
在全局:能够使用内置命名空间中的名字,不能够用局部命名空间的名字
在内置:没有局部和全局命名空间的名字spa

注意:当咱们在全局定义了和内置命名空间中同名的名字时,会使用全局的名字3d

print = "xx"
print(print)

Traceback (most recent call last):
  File "E:/LearnPython/review/test.py", line 4, in <module>
    print(print)
TypeError: 'str' object is not callable

做用域:2种code

全局做用域:做用在全局 —— 内置和全局命名空间中的名字都属于全局做用域 globals()
局部做用域:做用在局部 —— 函数(局部命名空间中的名字属于局部做用域)locals()blog

对于不可变数据类型,在局部能够查看全局做用域中的变量,可是不能直接修改。
若是想要修改,须要在程序的一开始添加global声明(尽可能避免使用global,不安全,会对全局产生影响)
若是在一个局部(函数)内声明了一个global变量,那么这个变量在局部的全部操做将对全局的变量有效。内存

例如:作用域

a = 1
def func():
    global a  # 声明
    a += 1    # 对a进行操做
    print(a)  # 2

func()

print(a)  # 2
#报错 UnboundLocalError: local variable 'a' referenced before assignment
a = 1
def func():
    a += 1
    print(a)

func()

globals() 与 locals()

globals()  永远打印全局的名字
locals()    输出什么是根据locals所在的位置

a = 1

def func():
    b = 2
    print(locals())
    print(globals())
    
func()
print(globals())
print(locals())

函数的嵌套调用

def max1(a, b):
    return a if a > b else b

def max2(x, y, z):
    ret1 = max1(x, y)  # 函数调用,用ret1接收返回值
    return max1(ret1, z)  # 再次调用,用ret2接收返回值

ret2 = max2(1, 2, 3)
print(ret2)  # 3

nonlocal:只能用于声明局部变量,找上层中离当前函数最近一层的局部变量
注意:声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量

a = 10
def outer():
    a = 20
    def inner1():
        b = 30
        def inner2():
            nonlocal a
            a += 1  # 修改变量a,对局部(有关联的最近一层)有影响,对全局没影响
            print("局部第三层:", a)
        inner2()
        print("局部第二层:", b)
    inner1()
    print("局部第一层", a)
    
outer()
print("全局 :", a)

做用域链:使用变量的时候,先从本身的名字空间找,找不到就向外一层一层地找,直到找到为止,找不到就报错。

函数名:

  1. 函数名能够赋值给一个变量
  2. 函数名能够做为容器类型的元素
  3. 函数名能够做为函数的返回值
  4. 函数名能够做为另外一个函数的参数
def func():
    print(123)

func()  # 函数名就是内存地址
func_ = func  # 函数名能够赋值
func_()

l = [func, func_]  # 函数名能够做为容器类型的元素
print(l)

for i in l:
    i()

def func1():
    print(123)  # 123

def func2(f):
    f()
    return f  # 函数名能够做为函数的返回值

func3 = func2(func1)  # 函数名能够做为另外一个函数的参数
func3()  # 123

闭包:是一个嵌套函数,内部函数调用外部函数的变量

def outer():
    name = "ppd"
    def inner():
        print(name)  # 内部inner函数调用了外部outer函数的变量name print(inner.__closure__)

outer()

打印一个函数的closure,有cell就证实是一个闭包。

闭包最多见的用法,在函数的外部去使用它内部的函数。

def outer():
    name = "ppd"
    def inner():
        print(name)
    return inner

func = outer()
func()  # ppd
print(func.__name__)  # inner
print(func.__closure__)  # (<cell at 0x0000000000695D68: str object at 0x00000000010AB378>,)
相关文章
相关标签/搜索