Python 全局空间和局部空间


Posted in Python onApril 06, 2022

一、空间和局部空间

1、命名空间

命名空间的概念的提出是为了划分和控制变量是否可见,以及生存周期的长短;命名空间的作用范围叫做作用域。
划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系)。一共三种。

内建命名空间:
解释器启动时创建,直到解释器运行结束,生存周期最长;
全局命名空间:
文件运行时创建,直到解释器运行结束,生存周期较长;
局部命名空间:
数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短;
创建和销毁顺序
创建顺序:
python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
销毁顺序:
函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据

2、全局变量和局部变量

什么是全局和局部变量:

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

# 在函数中创建的变量就是局部变量
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中自带的、内置的函数。

3、作用域

局部变量作用域:在函数的内部
全局变量作用域:横跨整个文件

4、生命周期

内置变量 -> 全局变量 -> 局部变量
内置变量自python程序运行的时候开始,一直等到python程序结束之后才会释放;
全局变量自创建开始,一直到程序结束或者被清除才会释放;
局部变量字创建开始,一直到局部空间执行结束或者清除就会释放;

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

函数

Python 全局空间和局部空间

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

关键字

Python 全局空间和局部空间

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)  # 局部环境中修改

6、函数的嵌套

在学习nonlocal之前我们需要先学习一些关于函数嵌套的知识。

内函数和外函数

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

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

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

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


# 执行外函数
outer()

'''
结果:
我叫outer,是外函数
我叫inner,在outer的里面,是内函数
'''
  • 内函数不可以直接在外函数外执行调用
  • 调用外函数后,内函数也不可以在函数外部调用
  • 内函数只可以在外函数的内部调用
  • 内函数在外函数内部调用时,有先后顺序,必须先定义在调用,因为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):当前函数内的作用域           (局部作用域)

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

三、总结

全局变量和局部变量

局部环境中可以调用全局变量,但是不能修改(但是如果全局变量是可变数据则可以修改其中的值)
全局环境中不能调用局部变量 也不能修改

函数
global()
(在函数内部使用,可以对全局变量进行操作)

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

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

关键字:

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

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

到此这篇关于Python 全局空间和局部空间的文章就介绍到这了,更多相关Python命名空间内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
微信跳一跳python自动代码解读1.0
Jan 12 Python
50行Python代码实现人脸检测功能
Jan 23 Python
Python callable()函数用法实例分析
Mar 17 Python
python pandas实现excel转为html格式的方法
Oct 23 Python
Python实现的拉格朗日插值法示例
Jan 08 Python
python递归法实现简易连连看小游戏
Mar 25 Python
使用PyCharm进行远程开发和调试的实现
Nov 04 Python
Python函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数用法实例分析
Dec 26 Python
pytorch 利用lstm做mnist手写数字识别分类的实例
Jan 10 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
Feb 21 Python
python pandas移动窗口函数rolling的用法
Feb 29 Python
详解如何使用Pytest进行自动化测试
Jan 14 Python
Selenium浏览器自动化如何上传文件
Apr 06 #Python
在Python 中将类对象序列化为JSON
Apr 06 #Python
Python中itertools库的四个函数介绍
Apr 06 #Python
如何用六步教会你使用python爬虫爬取数据
基于Python实现射击小游戏的制作
python使用opencv对图像添加噪声(高斯/椒盐/泊松/斑点)
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
You might like
PHP取余函数介绍MOD(x,y)与x%y
2014/05/15 PHP
网站防止被刷票的一些思路与方法
2015/01/08 PHP
Laravel中的Blade模板引擎示例详解
2017/10/10 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
2017/12/25 PHP
php使用redis的几种常见操作方式和用法示例
2020/02/20 PHP
PHP并发场景的三种解决方案代码实例
2021/02/27 PHP
JavaScript在IE中“意外地调用了方法或属性访问”
2008/11/19 Javascript
关于jquery css的使用介绍
2013/04/18 Javascript
javascript页面动态显示时间变化示例代码
2013/12/18 Javascript
JavaScript日期时间格式化函数分享
2014/05/05 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
jQuery中each()方法用法实例
2014/12/27 Javascript
JS简单模拟触发按钮点击功能的方法
2015/11/30 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
2016/08/02 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
2017/06/09 Javascript
JS处理数据四舍五入(tofixed与round的区别详解)
2017/10/26 Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
2019/12/17 Javascript
jquery实现进度条状态展示
2020/03/26 jQuery
Python脚本实现下载合并SAE日志
2015/02/10 Python
Python中修改字符串的四种方法
2018/11/02 Python
python读取并定位excel数据坐标系详解
2019/06/26 Python
python OpenCV GrabCut使用实例解析
2019/11/11 Python
pytorch中的上采样以及各种反操作,求逆操作详解
2020/01/03 Python
Python实现屏幕录制功能的代码
2020/03/02 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
python/golang实现循环链表的示例代码
2020/09/14 Python
python 制作简单的音乐播放器
2020/11/25 Python
Rag & Bone官网:瑞格布恩高级成衣
2018/04/19 全球购物
Manduka官网:瑜伽垫、瑜伽毛巾和服装
2018/07/02 全球购物
SportsDirect.com新加坡:英国第一体育零售商
2019/03/30 全球购物
介绍一下Ruby的多线程处理
2013/02/01 面试题
超市后勤自我鉴定
2014/01/17 职场文书
即将毕业大学生自荐信
2014/01/24 职场文书
社区服务活动小结
2014/07/08 职场文书
党小组意见范文
2015/06/08 职场文书
JavaScript控制台的更多功能
2021/04/28 Javascript