乐趣区

关于python:Python-函数进阶全局空间和局部空间

全局空间和部分空间

命名空间

命名空间的概念的提出是为了划分和控制变量是否可见,以及生存周期的长短;命名空间的作用范畴叫做作用域。

划分一块区域保留所有数据,以字典的形式存储(变量与值造成映射关系)。一共三种。

  1. 内建命名空间:

    • 解释器启动时创立,直到解释器运行完结,生存周期最长;
  2. 全局命名空间:

    • 文件运行时创立,直到解释器运行完结,生存周期较长;
  3. 部分命名空间:

    • 数调用时,外面的局部变量才创立,调用完结后即开释,生存周期较短;

创立和销毁程序

  • 创立程序:

    • python 解释器启动 -> 创立内建命名空间 -> 创立全局命名空间 -> 创立部分命名空间
  • 销毁程序:

    • 函数调用完结后 -> 销毁函数对应的部分命名空间数据 -> 销毁全局命名空间数据 -> 销毁内建命名空间数据

全局变量和局部变量

什么是全局和局部变量

局部变量就是在函数外部定义的变量,局部变量所在的就是部分命名空间,作用域仅仅在函数外部可见,也就是说只能在函数外部应用。

# 在函数中创立的变量就是局部变量
def func():
   var = '局部变量'

# 局部变量不能够在非对应部分环境中应用
print(var)  # error, 该变量不存在

全局变量就是在函数内部定义的或者应用 global 在函数外部定义的变量,全局变量所在的命名空间就是全局命名空间,作用域横跨整个文件,就是说在整个文件中的任何一个中央都能够应用全局变量。

# 在全局环境中创立的变量就是全局变量
var = '全局变量'

def func():
    # 在部分中也能够应用全局变量
    print(var)  # 全局变量

func()

局部变量最好不要和全局变量同名,如果同名,在部分环境中就无奈应用全局变量了。

var = '全局变量'

def func():
    # 先应用了全局变量
    print(var)  # error, 找不到该变量

    # 而后局部变量和全局变量同名,那么新的局部变量就会在部分空间中笼罩了全局变量的所有影响力,这就叫做局部变量批改了全局变量;# 这样的话导致在部分空间中无奈在应用该全局变量,之前在部分空间中应用的该变量就成为了先调用后定义;导致出错。var = '局部变量'
    print(var)

func()

# 然而部分同名变量不会影响到全局变量的值
print(var)  # 全局变量

内置函数就是内建命名空间,指的是那些 python 中自带的、内置的函数。

作用域

局部变量作用域:在函数的外部

全局变量作用域:横跨整个文件

生命周期

内置变量 -> 全局变量 -> 局部变量

内置变量自 python 程序运行的时候开始,始终等到 python 程序完结之后才会开释;

全局变量自创立开始,始终到程序完结或者被革除才会开释;

局部变量字创立开始,始终到部分空间执行完结或者革除就会开释;

全部分函数和关键字的应用

函数

函数 作用
globals() 寄存着全局作用域中的所有内容,以字典的模式返回
locals() 寄存着以后作用域中的所有内容,以字典的模式返回
globals()

返回所有的全局作用域中的内容。

如果在全局,调用 globals 之后,获取的是打印之前的所有变量,返回字典,全局空间作用域;

# 定义一些全局变量
a, b, c = 1, 2, 3

# 调用 globals 函数
res = globals()

# 第一次打印,蕴含 a b c
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002DBDCA5D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}}
'''


# 再定义一些变量
d, e, f = 1, 2, 3

# 第二次打印,蕴含 a b c d e f
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002DBDCA5D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}, 'd': 1, 'e': 2, 'f': 3}
'''

如果在部分,调用 globals 之后,获取的是调用之前的所用变量,返回字典,全局空间作用域;

# 定义一些全局变量
a, b, c = 1, 2, 3


# 在部分环境中应用 globals 函数
def func():
    res = globals()
    print(res)


# 调用函数
func()
'''
后果:不蕴含 d e f
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E7C287D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': <function func at 0x000001E7C2772F28>}
'''


# 再定义一些全局变量
d, e, f = 4, 5, 6

# 第二次调用函数
func()
'''
后果:蕴含 d e f
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000021A3F3DD198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': <function func at 0x0000021A3F2D2F28>, 'd': 4, 'e': 5, 'f': 6}
'''

globals 能够动态创建全局变量

dic = globals()

print(dic)  # 返回零碎的字典
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000026F357ED198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}}
'''


# 在全局的字典当中,通过增加键值对,主动创立全局变量,对应的键是变量名,对应的值是变量指向的值
dic['msr123123123'] = '123456'

print(msr123123123)    # 123456

# 查看全局内容
print(dic)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000161D944D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}, 'msr123123123': '123456'}
'''
locals()

返回以后所在作用域的所有内容。

如果在全局,调用 locals 之后,获取的是打印之前的所有变量,返回字典,全局空间作用域;

# 定义一些全局变量
a, b, c = 1, 2, 3

# 调用 locals 函数
res = locals()

# 第一次打印,蕴含 a b c
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018C82A3D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test1.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}}
'''


# 再定义一些变量
d, e, f = 1, 2, 3

# 第二次打印,蕴含 a b c d e f
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018C82A3D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test1.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}, 'd': 1, 'e': 2, 'f': 3}
'''

如果在部分,调用 locals 之后,获取的是调用之前的所有变量,返回字典,部分空间作用域;

# 定义一些局部变量
def func():
   # 局部变量
   aa, bb, cc = 11, 22, 33

   # 第一遍调用
   res = locals()

   # 第一次打印,蕴含 aa bb cc
   print(res)  # {'cc': 33, 'bb': 22, 'aa': 11}

   # 再定义一些局部变量
   dd, ee, ff = 44, 55, 66

   # 第二次打印,不蕴含 dd ee ff
   print(res)  # {'cc': 33, 'bb': 22, 'aa': 11}

   # 调用第二遍
   res2 = locals()

   # 打印第一次的调用,蕴含 dd ee ff
   print(res)  # {'cc': 33, 'bb': 22, 'aa': 11, 'ff': 66, 'ee': 55, 'dd': 44, 'res': {...}}
   
   # 打印第二次的调用,蕴含 dd ee ff
   print(res2) # {'cc': 33, 'bb': 22, 'aa': 11, 'ff': 66, 'ee': 55, 'dd': 44, 'res': {...}}

# 调用函数,返回在函数中的局部变量
func()

关键字

关键字 作用
global 申明全局变量、获取应用和批改全局变量的权限
nonlocal 批改局部变量(以后函数的上一层的局部变量)
global

在部分环境中创立的变量是局部变量,在全局环境中是不能够应用的。然而应用 global 定义的变量就是一个全局变量,这个变量能够全局环境中应用。

def func():
    var = '局部变量'

    global glvar
    glvar = '全局变量'

# 肯定要执行部分环境哟
func()

# 全局环境中
print(var)  # error,局部变量不能调用
# 应用 global 定义的变量是全局变量
print(glvar)    # 全局变量

在部分环境中无奈批改全局变量的值,应用 global 能够在部分环境中批改全局变量。

var = '全局变量'

def func():
    global var
    var = '部分环境中批改'

func()

print(var)  # 部分环境中批改

函数的嵌套

在学习 nonlocal 之前咱们须要先学习一些对于函数嵌套的常识。

内函数和外函数

函数之间是能够相互嵌套的,外层的叫做外函数,内层的叫做内函数。

def outer():
    print('我叫 outer,是外函数')

    def inner():
        print('我叫 inner,在 outer 的外面,是内函数')

    # 在外函数中执行内函数
    inner()


# 执行外函数
outer()

'''
后果:我叫 outer,是外函数
我叫 inner,在 outer 的外面,是内函数
'''
  1. 内函数不能够间接在外函数外执行调用
  2. 调用外函数后,内函数也不能够在函数内部调用
  3. 内函数只能够在外函数的外部调用
  4. 内函数在外函数外部调用时,有先后顺序,必须先定义在调用,因为 python 没有预读机制,这个预读机制实用于 python 中的所有场景。
# 外层是 outer,内层是 inner,最里层是 smaller,调用 smaller 里的所有代码
def outer():
    print('我叫 outer,是最外层函数,是 inner 和 smaller 的外函数')

    def inner():
        print('我叫 inner,是 outer 的内函数,是 smaller 的外函数')

        def smaller():
            print('我叫 smaller,是 outer 和 inner 的内函数')

        # 先在 inner 中执行 smaller
        smaller()

    # 而后在 outer 中执行 inner
    inner()

# 最初再执行 outer 能力执行 smaller 函数
outer()

'''
后果:我叫 outer,是最外层函数,是 inner 和 smaller 的外函数
我叫 inner,是 outer 的内函数,是 smaller 的外函数
我叫 smaller,是 outer 和 inner 的内函数
'''

咱们在多个函数嵌套的时候要留神,不论外函数还是内函数,都是函数,只有是函数中的变量都是局部变量。

外延能够应用外函数的局部变量,外函数不能间接应用内函数的局部变量。

LEGB 准则

LEGB 准则就是一个就近找变量准则,根据就近准则,从下往上,从里向外,顺次寻找。

B————Builtin(Python):Python 内置模块的命名空间(内建作用域)G————Global(module):函数内部所在的命名空间(全局作用域)E————Enclosing Function Locals:内部嵌套函数的作用域(嵌套作用域)L————Local(Function):以后函数内的作用域(部分作用域)

nonlocal

当初咱们正式学习 nonlocal 关键字,nonlocal 的作用是批改以后部分环境中上一层的局部变量。那么咱们依据这个作用便晓得了 nonlocal 的应用环境至多是一个二级的嵌套环境,且外层的部分环境中必须存在一个局部变量。

def outer():
    # 定义变量
    lvar = 'outer var'

    def inner():
        # 内函数应用 nonlocal 批改上一层的局部变量
        nonlocal lvar
        lvar = 'inner var'

    # 执行 inner 函数
    inner()
    print(lvar)

outer() # inner var

如果上一层的部分环境中没有这个变量怎么办,那么就依据 LEGB 准则向上寻找。

def outer():
    # 定义变量
    lvar = 'outer var'

    def inner():
        
        def smaller():
            
            # smaller 中批改变量,然而 inner 中没有,就向上寻找批改 outer 中的变量
            nonlocal lvar
            lvar = 'smaller var'

        # 执行 smaller 函数
        smaller()

    # 执行 inner 函数
    inner()
    print(lvar)

# 执行 outer 函数
outer()

如果层层寻找,直到最外层的函数中也没有这个变量,那么就会报错,因为 nonlocal 只会批改局部变量,如果超出范围,就会报错。

var = 1  # 变量在最外层的函数之外,也就是全局变量,nonlocal 无奈批改

def outer():

   def inner():

      def smaller():

         nonlocal var    # error,没有局部变量
         var = 2
         print(var)

      smaller()

   inner()

outer()

总结

全局变量和局部变量

部分环境中能够调用全局变量,然而不能批改(然而如果全局变量是可变数据则能够批改其中的值)
全局环境中不能调用局部变量 也不能批改

函数

global()

(在函数外部应用,能够对全局变量进行操作)
1、能够在部分环境中定义全局变量
2、能够在部分环境中批改全局变量

nonlocal()

(在内函数中应用,能够在内函数中批改外函数中的局部变量)

关键字

locals

1、locals 获取以后作用域当中所有的变量
如果在全局调用 locals 之后,获取的是打印之前的所有变量,返回字典,全局作用域
如果在部分调用 loclas 之后,获取的是调用之前的所有变量,返回字典,部分作用域

globals

2、globals 只获取全局空间中的所有变量
如果在全局调用 globals 之后,获取的是打印之前的所用变量,返回字典,全局作用域
如果在部分调用 globals 之后,获取的是调用之前的所用变量,返回字典,全局作用域

退出移动版