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


    命名空间:3种

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

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

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

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

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

    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种

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

    对于不可变数据类型,在局部可以查看全局作用域中的变量,但是不能直接修改。
    如果想要修改,需要在程序的一开始添加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>,)
  • 相关阅读:
    高并发计算服务器数量
    Java子线程中操作主线程Private级别数据
    Java线程并发中常见的锁--自旋锁 偏向锁
    Java锁之自旋锁详解
    Java多线程:向线程传递参数的三种方法
    TPS、并发用户数、吞吐量关系
    C/C++中near和far的区别
    qt的pos()和globalpos()(globalpos是相对于桌面的)
    如何获得 Qt窗口部件在主窗口中的位置--确定鼠标是否在某一控件上与在控件上的位置
    QComboBox实现复选功能(三种方法:嵌套QListWidget, 设置QStandardItemModel, 设置Delegate)
  • 原文地址:https://www.cnblogs.com/believepd/p/9567010.html
Copyright © 2020-2023  润新知