首页 > 编程语言 >【2.0】Python高级之名称空间与作用域

【2.0】Python高级之名称空间与作用域

时间:2023-11-20 09:47:22浏览次数:50  
标签:全局变量 fun1 函数 作用域 Python 2.0 def 变量

【一】名称空间与闭包

【1】什么是名称空间

  • 名称空间即存放名字与对象映射/绑定关系的地方。
    • 对于x=3
    • Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中
    • del x表示清除该绑定关系。
  • 在程序执行期间最多会存在三种名称空间

【2】内建名称空间

  • 伴随python解释器的启动/关闭而产生/回收
    • 因而是第一个被加载的名称空间,用来存放一些内置的名字,比如内建函数名
print(max)
# <built-in function max>

【3】全局名称空间

  • 伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,如下名字
import sys #模块名sys

x=1 #变量名x

if x == 1:
    y=2 #变量名y

def foo(x): #函数名foo
    y=1
    def bar():
        pass

Class Bar: #类名Bar
	pass

【4】局部名称空间

  • 伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中
def foo(x):
    y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中

【5】名称空间的加载顺序是

  • 内置名称空间->全局名称空间->局部名称空间,
  • 而查找一个名字,必须从三个名称空间之一找到,查找顺序为:
  • 局部名称空间->全局名称空间->内置名称空间。

【二】作用域

【1】变量作用域

  • 变量的作用域
    • Python是静态作用域,也就是说Python中,变量的作用域源于它在代码中的位置
    • 在不同的位置,可能有不同的命名空间。命名空间是变量作用域的体现形式
  • python变量作用域一般有4种:
    • Local(局部变量)
    • Enclosed(嵌套)
    • Global(全局)
    • Built-in(内置)

(1)Local(局部变量)

  • Local(局部变量):暂时的存在,依赖于创建该局部作用域的函数。函数存,则局部变量存,函数亡,则局部变量亡。

  • 作用范围:当前整个函数体范围

    # 定义一个函数,函数内部就是局部作用域
    def fun():
        # 只有在函数内部的变量
        b = 2
        print(b)  # 输出2
    
    
    fun()
    # 调用函数后,发现找不到变量 b 是因为在全局作用域中找不到 变量 b
    print(b)  # 报错
    
    '''
    Traceback (most recent call last):
      File "E:\PythonProjects\def_func.py", line 16, in <module>
        print(b)  # 报错
    NameError: name 'b' is not defined
    '''
    

    img

(2)Enclosed(嵌套)

  • Enclosed(嵌套):一般是在函数中嵌套函数的时候,外层函数的变量作用域。

  • 作用范围:闭包函数

    # Enclosed(嵌套)作用域
    def fun1():
        b = 2
        print("这是fun1打印的:", b)
    
        def fun2():
            # 函数 func1 里面 嵌套的 函数 func2 里面的作用域就是 嵌套作用域
            print("这是fun2打印的:", b)
        
        # 将内部函数 func2 的内存地址返回
        return fun2
    
    
    # 调用 函数 fun1 , 函数 func1 的返回值是内部函数 fuc2的函数地址
    temp = fun1()
    
    # 调用 函数 fun1 的返回值(fuc2的函数地址) , 从而执行 函数 fuc2
    temp()
    # 这是fun1打印的: 2
    # 这是fun2打印的: 2
    
    • 在这里函数fun2里面并没有定义变量b,但是它能够引用外层函数fun1定义的b变量,此时变量b的作用域就是Enclosed

      img

(3)Global(全局)

  • Global(全局):一般模块文件顶层声明的变量具有全局作用域,从外部来看,模
    块的全局变量就是一个模块对象的属性,仅限于单个模块文件中。
  • 作用范围:当前模块(文件)
# Global(全局)作用域

# 定义在全局的变量,在本文件任意位置可调用该变量
a = 2


def fun1():
    print("这是fun1打印的:", a)


fun1()
print(a)

# 这是fun1打印的: 2
# 2

img

(4)Built-in(内置)

  • Built-in(内置):解释器内置的变量,比如int, str等。

  • 作用范围:所有模块(文件)

  • Python中没有块级作用域。

  • 块级作用域:代码块中的变量,比如if、while、for后面的代码

【2】LEGB规则

  • LGEB规则:按照L--->E--->G--->B的顺序查找变量。
    • 也就是,当不同命名空间具有相同变量名称的变量时,我们首先查找局部变量,如果没有查到,再向全局变量查找。

(1)基于命名空间的常见变量类型

  • 局部变量:
    • 在一个函数体的内部定义的变量
    • 作用域为函数内部
    • 查看局部变量命令:locals()
  • 全局变量
    • 在函数体外部,文件最外层定义的变量
    • 作用域为整个文件内部
    • 查看全局变量命令:globals()
  • 注意:
    • 变量访问规则:从内到外
    • 全局变量和局部变量重名时,采用就近原则

(2)案例讲解

# 定义了一个全局变量G,并把"G全局"赋值给a
a = "G全局"


def myfunc():
    # 定义了一个局部变量a,并把"E局部1"赋值给a
    a = "E局部"

    def inner():
        # 定义了一个局部变量a,并把"L局部2"赋值给a
        a = "L局部2"
        print(f"inner打印的a:{a}")

    inner()
    print(f"myfunc打印的a:{a}")


myfunc()
print(f"__main__打印的a:{a}")
# inner打印的a:L局部2
# myfunc打印的a:E局部
# __main__打印的a:G全局
  • 结果如下

    img

  • 代码结果分析流程

    img

(3)变量的使用规则

  • 创建变量时从上往下创建,搜索变量时从下往上搜索。
  • 创建变量时,下层变量会覆盖上层同名变量,但不会改变上层变量的值,除非使用gloable和nonlocal关键字声明

img

【3】变量的修改

(1)global修改全局变量

  • 一般全局变量一经定义后几乎是不用改的,也不允许在局部修改全局变量,除非使用Global关键字声明。

    # 定义一个全局变量 a
    a = 1
    
    
    def fun1():
        # 修改全局变量
        a = a + 2
        print(a)
    
    
    fun1()
    print(a)
    '''
    Traceback (most recent call last):
      File "E:\PythonProjects\def_func.py", line 97, in <module>
        fun1()
      File "E:\PythonProjects\def_func.py", line 93, in fun1
        a = a + 2
    UnboundLocalError: local variable 'a' referenced before assignment
    '''
    

    img

  • 可以看到,当我们试图在函数fun1创建的局部作用域内改变全局变量a就会报错

    • 但如果在修改之前使用global关键字声明时,就会正常修改外部的全局变量a

      # 定义一个全局变量 a
      a = 1
      
      
      def fun1():
          global a
      
          # 修改全局变量
          a = a + 2
          print(f"函数内部修改全局变量 :>>>> {a}")
      
      
      fun1()
      print(f"调用函数后全局变量 :>>>> {a}")
      # 函数内部修改全局变量 :>>>> 3
      # 调用函数后全局变量 :>>>> 3
      

      img

(2)nonlocal修改外层函数变量

  • 在函数中嵌套函数时,嵌套在里面的函数创建的作用域内一般也是不允许改变外层函数变量的值的

  • 除非是nonlocal关键字声明

  • 如下

    # 不使用nonocal声明,修改外层函数变量值
    def fun1():
        a = 1
    
        def fun2():
            a += 2
            print(a)
    
        return fun2
    
    
    temp = fun1()  # 调用fun1
    temp()  # 调用fun2
    '''
    Traceback (most recent call last):
      File "E:\PythonProjects\def_func.py", line 137, in <module>
        temp()  # 调用fun2
      File "E:\PythonProjects\def_func.py", line 130, in fun2
        a += 2
    UnboundLocalError: local variable 'a' referenced before assignment
    '''
    

    img

  • 可以看到,报错和在函数内不使用global修改全局变量报的错是一样的

  • 当使用nonlocal声明后再修改就不会报错了

    # 不使用nonocal声明,修改外层函数变量值
    def fun1():
        a = 1
        print(f"我是func1的变量修改前:{a}")
    
        def fun2():
            nonlocal a  # 使用nonocal声明
            a += 2
            print(f"这是内层嵌套修改局部变量后 :>>>> {a}")  # 修改后
    
        print(f"我是func1的变量修改后:{a}")
        return fun2
    
    
    temp = fun1()  # 调用fun1
    temp()  # 调用fun2
    
    # 我是func1的变量修改前:1
    # 我是func1的变量修改后:1
    # 这是内层嵌套修改局部变量后 :>>>> 3
    

    img

  • 可以看到是正常修改的

标签:全局变量,fun1,函数,作用域,Python,2.0,def,变量
From: https://www.cnblogs.com/dream-ze/p/17843225.html

相关文章

  • 【1.0】Python高级之函数
    【一】函数的基本使用基于前一部分的学习,我们已经能开发一些功能简单的小程序了但随着程序功能的增多,代码量随之增大此时仍不加区分地把所有功能的实现代码放到一起,将会使得程序的组织结构不清晰,可读性变差,且程序中需要频繁使用同一功能时,只能重复编写该功能的实现代码,日积月......
  • 创建Conda环境时,自动包含当前系统中的Python和CUDA等
    要在创建Conda环境时自动包含当前系统中的Python和CUDA,可以使用Conda的environment.yml文件。environment.yml文件是一个文本文件,其中包含了创建Conda环境所需的依赖项信息。下面是一个示例的environment.yml文件,其中包含了Python和CUDA的依赖项:yaml复制代码 name:myenv......
  • [oeasy]python001_先跑起来_python_三大系统选择_windows_mac_linux
    先跑起来......
  • Linux环境下Python3.10安装
    事件缘起我在Linux服务器(CentOS7.8)安装Python3.10,并替换python软链接为python3之后,yum命令不可用。特此记录一下。完整安装步骤如下:Python3.10安装1.使用yum程序提前安装Python依赖。yuminstallwgetzlib-develbzip2-developenssl-develncurses-develsqlite-develr......
  • 【Python进阶】近200页md文档14大体系知识点,第4篇:linux命令和vim使用
    本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。全套Python进阶笔记地址:请移步这里共......
  • 【Python】【OpenCV】【NumPy】图像和原始字节的转换
    学习完基础的图像算法,开始接触OpenCV学习:灰度图中,一个像素点上的灰度级需要一个字节(byte,2^8,8bit)进行存储,此时的灰度图是二维的。而当我们需要转换为彩色图时,即三维,便会产生颜色通道(Channel),这个时候,一个像素点上的灰度级便会需要三个字节来进行存储。可以借助笛卡尔坐标系来帮助......
  • Python装饰器-计算运行时间小例子
    importtimedefrun_time(func):"计算运行时长装饰器"defwrapper(*args,**kwargs):#包装函数start=time.time()#在调用装饰函数前干点事情res=func(*args,**kwargs)end=time.time()#在调用装饰函数后干点事情t=e......
  • 掌握迭代器:Python中的强大工具,让你轻松驾驭数据处理的巨轮
    今天,我们将深入探讨Python中的迭代器。迭代器是一种强大的工具,它使我们能够在不需要知道数据集的全部信息的情况下,逐个访问数据集中的每个元素。通过使用迭代器,我们可以逐个处理数据集中的每个元素,而不需要一次性加载整个数据集到内存中。这使得迭代器在处理大型数据集时特别有用。......
  • python代码压缩
    python代码压缩使用python-minifier库压缩python文件大小,同时混淆代码。安装库:pipinstallpython-minifier,对于单个文件或整个项目都可以直接使用命令压缩。使用python-minifier压缩pydantic的模型时会有问题,暂时过滤掉对应文件,因此写了一个脚本来压缩整个项目到另一个......
  • Windows部署Python环境
    下载Python解释器进入Python官网。在Downloads下,选择Windows。找到自己需要的Python版本,点击进行下载。双击运行Python解释器安装包。选中Addpython.exetoPATH,然后单击Customizeinstallation进行自定义安装。注意,一定要选择Addpython.exetoPATH将python命令加......