Python 函数进阶-全局空间和局部空间

全局空间和局部空间

命名空间

命名空间的概念是为了划分和控制变量是否可见以及生命周期的长度;命名空间的作用域称为作用域。

[En]

The concept of namespaces is proposed to divide and control whether variables are visible and the length of the life cycle; the scope of namespaces is called scope.

划分一个区域来存储所有数据,并将其存储在一个词典中(变量和值形成映射关系)。有三种。

[En]

Divide an area to store all data and store it in a dictionary (variables and values form a mapping relationship). There are three kinds.

  1. 内建命名空间:
  2. 解释器启动时创建,直到解释器运行结束,生存周期最长;
  3. 全局命名空间:
  4. 文件运行时创建,直到解释器运行结束,生存周期较长;
  5. 局部命名空间:
  6. 数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短;

创建和销毁顺序

  • 创建顺序:
  • python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
  • 销毁顺序:
  • 函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据

全局变量和局部变量

什么是全局和局部变量

局部变量是在函数内部定义的变量,局部变量在局部命名空间中,作用域只在函数内部可见,也就是说只能在函数内部使用。

[En]

The local variable is the variable defined inside the function, the local variable is in the local namespace, and the scope is only visible inside the function, that is to say, it can only be used inside the function.

在函数中创建的变量是局部变量<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>The variables created in the function are local variables</font>*</details>
def func():
   var = '局部变量'

局部变量不能在非对应的局部环境中使用<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Local variables cannot be used in non-corresponding local environments</font>*</details>
print(var)  # error, 该变量不存在

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

在全局环境中创建的变量是全局变量。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Variables created in the global environment are global variables.</font>*</details>
var = '全局变量'

def func():
    # 在局部中也可以使用全局变量
    print(var)  # 全局变量

func()

最好不要使用与全局变量同名的局部变量。如果它们具有相同的名称,则不能在本地环境中使用全局变量。

[En]

It is best not to use local variables with the same name as global variables. If they have the same name, global variables cannot be used in the local environment.

var = '全局变量'

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

    # 然后局部变量和全局变量同名,那么新的局部变量就会在局部空间中覆盖了全局变量的一切影响力,这就叫做局部变量修改了全局变量;
    # 这样的话导致在局部空间中无法在使用该全局变量,之前在局部空间中使用的该变量就成为了先调用后定义;导致出错。
    var = '局部变量'
    print(var)

func()

但是,同名的局部变量不会影响全局变量的值。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>However, local variables with the same name will not affect the value of global variables.</font>*</details>
print(var)  # 全局变量

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

作用域

局部变量作用域:函数内部

[En]

Local variable scope: inside the function

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

[En]

Global variable scope: across the entire file

生命周期

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

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

在程序完成或清除之前,全局变量不会从创建中释放。

[En]

Global variables are not released from creation until the program is finished or cleared.

局部变量字的创建开始并将被释放,直到局部空间执行完成或被清除。

[En]

The creation of the local variable word begins and will be released until the local space execution is finished or cleared.

全局部函数和关键字的使用

函数

函数 作用 globals() 存放着全局作用域中的所有内容,以字典的形式返回 locals() 存放着当前作用域中的所有内容,以字典的形式返回

globals()

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

[En]

Returns the contents of all global scopes.

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

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

调用globals函数
res = globals()

第一次打印,包含a b c
print(res)
'''
结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__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__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__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__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': }
'''

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

第二次调用函数
func()
'''
结果:包含 d e f
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': , 'd': 4, 'e': 5, 'f': 6}
'''

globals可以动态创建全局变量

dic = globals()

print(dic)  # 返回系统的字典
'''
结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}}
'''

在全局字典中,通过添加键-值对自动创建全局变量。对应的键是变量名,对应的值是变量指向的值。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>In the global dictionary, a global variable is automatically created by adding a key-value pair. The corresponding key is the variable name and the corresponding value is the value pointed to by the variable.</font>*</details>
dic['msr123123123'] = '123456'

print(msr123123123) # 123456

查看全局内容
print(dic)
'''
结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}, 'msr123123123': '123456'}
'''
locals()

返回当前作用域的所有内容。

[En]

Returns all contents of the current scope.

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

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

调用locals函数
res = locals()

第一次打印,包含a b c
print(res)
'''
结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__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__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__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': {...}}

调用函数以返回函数中的局部变量<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Call the function to return the local variable in the function</font>*</details>
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之前我们需要先学习一些关于函数嵌套的知识。

内函数和外函数

函数可以相互嵌套。外层称为外部函数,内层称为内部函数。

[En]

Functions can be nested within each other. The outer layer is called the outer function and the inner layer is called the inner function.

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的内函数
'''

当我们嵌套多个函数时,我们应该注意到,无论是外部函数还是内部函数,它都是一个函数,只要函数中的变量是局部变量。

[En]

When we nest multiple functions, we should note that no matter the outer function or the inner function, it is a function, as long as the variables in the function are local variables.

内涵可以使用外部函数的局部变量,外部函数不能直接使用内部函数的局部变量。

[En]

The connotation can use the local variable of the outer function, and the outer function cannot directly use the local variable of the inner function.

LEGB原则

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

B&#x2014;&#x2014;&#x2014;&#x2014;Builtin&#xFF08;Python&#xFF09;&#xFF1A;Python&#x5185;&#x7F6E;&#x6A21;&#x5757;&#x7684;&#x547D;&#x540D;&#x7A7A;&#x95F4;    &#xFF08;&#x5185;&#x5EFA;&#x4F5C;&#x7528;&#x57DF;&#xFF09;
G&#x2014;&#x2014;&#x2014;&#x2014;Global&#xFF08;module&#xFF09;&#xFF1A;&#x51FD;&#x6570;&#x5916;&#x90E8;&#x6240;&#x5728;&#x7684;&#x547D;&#x540D;&#x7A7A;&#x95F4;        &#xFF08;&#x5168;&#x5C40;&#x4F5C;&#x7528;&#x57DF;&#xFF09;
E&#x2014;&#x2014;&#x2014;&#x2014;Enclosing Function Locals&#xFF1A;&#x5916;&#x90E8;&#x5D4C;&#x5957;&#x51FD;&#x6570;&#x7684;&#x4F5C;&#x7528;&#x57DF;&#xFF08;&#x5D4C;&#x5957;&#x4F5C;&#x7528;&#x57DF;&#xFF09;
L&#x2014;&#x2014;&#x2014;&#x2014;Local&#xFF08;Function&#xFF09;&#xFF1A;&#x5F53;&#x524D;&#x51FD;&#x6570;&#x5185;&#x7684;&#x4F5C;&#x7528;&#x57DF;           &#xFF08;&#x5C40;&#x90E8;&#x4F5C;&#x7528;&#x57DF;&#xFF09;

Python 函数进阶-全局空间和局部空间

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()

总结

全局变量和局部变量

全局变量可以在本地环境中调用,但不能修改(但如果全局变量是变量数据,则可以修改该值)

[En]

A global variable can be called in a local environment, but cannot be modified (but the value can be modified if the global variable is variable data)

不能在全局环境中调用或修改局部变量

[En]

Local variables cannot be called or modified in the global environment

函数

global()

(在函数内使用,以操作全局变量)

[En]

(used inside a function to manipulate global variables)

1、可以在局部环境中定义全局变量
2、可以在局部环境中修改全局变量

nonlocal()

(在内部函数中使用,可以修改外部函数中的局部变量)

[En]

(used in the inner function, you can modify the local variables in the outer function)

关键字

locals

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

globals

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

Original: https://www.cnblogs.com/msr20666/p/16101151.html
Author: 小小垂髫
Title: Python 函数进阶-全局空间和局部空间

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/500102/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 5个拿来就能用的整人代码脚本

    「作者主页」:士别三日wyx「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 整蛊代码脚本 一、你的电脑正在被攻击!!! 二、CMD炸弹 …

    Python 2023年9月16日
    0113
  • 数据分析与可视化

    使用适当的分析方法对采集和整理后的数据加以详细研究,提取有用的信息和形成概括总结的过程。 &#x63D0;&#x793A;&#xFF1A;&#x8F…

    Python 2023年8月28日
    0128
  • 深入剖析堆原理与堆排序

    堆的介绍 完全二叉树:完全二叉树是满二叉树去除最后N个节点之后得到的树((N \geq0, N \in N^*)) 大根堆:节点的父亲节点比自身节点大,比如根节点的值为(8),比其…

    Python 2023年10月20日
    094
  • K-means算法

    概念 K-means算法也称为K_均值算法,用于聚类算法。聚类是一种无监督学习,他将相似的对象归于一个簇中,簇中心通过簇中所有点的均值来计算。聚类算法与分类算法的主要区别就是分类的…

    Python 2023年10月24日
    074
  • pyecharts绘制各种数据可视化图表案例(效果+代码)

    pyecharts绘制各种图表 * – + 1、pyecharts绘制饼图(显示百分比) + 2、pyecharts绘制柱状图 + 3、pyecharts绘制折线图 +…

    Python 2023年8月1日
    0178
  • 程序员核心——详解调试(2)

    所爱隔山海,山海皆可平,所念皆星河,星河不可及。 上课! 接着上节课讲的调试(1),本节课进一步讲解调试(2). 文章目录 1.调试实例讲解(2) 校招笔试题 2.如何写出好的(易…

    Python 2023年9月27日
    079
  • 模板语法之标签

    语法 {% &#x5F00;&#x59CB;&#x6807;&#x7B7E; %} …. {% &#x7ED3;&#x675F;…

    Python 2023年11月1日
    088
  • 时间序列—相关性和滞后性分析_python

    抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。 Original: https://blo…

    Python 2023年10月7日
    0108
  • Flask服务器与客户端基本通信【Unity网络编程(三)】

    这里先演示基于Python的客户端和服务器的登录实现。 1.Flask服务器端(GET和POST请求接收实现) 1.GET和POST区别:(简单理解) 1.GET因为是读取,就可以…

    Python 2023年8月10日
    0122
  • 手写数字识别-基于卷积神经网络

    🍈 一、必备知识 (1)手写数字 机器识图的过程:机器识别图像并不是一下子将一个复杂的图片完整识别出来,而是将一个完整的图片分割成许多个小部分,把每个小部分里具有的特征提取出来(也…

    Python 2023年8月2日
    091
  • Flask生产环境部署指南 | 复杂度– 稳定性++ 性能++

    自上次用flask搭了个接口跑yolo以后,一直都很ok 直到有一天请求数突然多了起来… 只要有1个以上线程请求就崩掉 查了一下原来app.run()是用于开发环境测试…

    Python 2023年8月13日
    0102
  • 记一次win10安装cupy的失败经历(附 cupy与numpy对比)

    win10 python38安装cupy中踩的n多个坑 问题的根源应该是我在装cupy之前把Nvidia cuda更新到了最新的11.5版本,原本是10.2版本。中间经历真是太狗血…

    Python 2023年8月25日
    098
  • python-print函数之sep、end参数

    sep是print函数里的一个参数,主要用来定义输出数据之间的间隔符号。 其主要用法如下: 1.输出数据之间换行输出 str1 str2 2.输出数据之间用空格间隔,其实默认格式就…

    Python 2023年11月1日
    084
  • JavaScript 设计模式及代码实现——代理模式

    代理模式 1 定义 为其他对象提供一种代理以控制对这个对象的访问 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 2 …

    Python 2023年10月23日
    0128
  • 【漏洞复现-Django-SQL注入】Django-SQL注入CVE-2021-35042

    2.1、分析: http://ip:port/vuln/?order=id (从1到4升序排列) (从4到1降序排列) 返回的数据随值的改变而改变 (带入到了数据库中被执行) 可以…

    Python 2023年8月3日
    097
  • 【Python手写笔记】 文件与异常,纯肝货

    前言 今天给大家分享一下我自己写的笔记,纯纯的都是干货,关于字好像也能看。这是我学python整理出来的一些资料,希望对大家 有用。想要更多的资料那就的给一个关注了… …

    Python 2023年11月2日
    077
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球