一、命名空间和作用域

当出现了函数,变量声明的位置就发生了变化,不同位置声明的变量,能访问这个变量的范围也出现了限制

1.1 定义

**命名空间:**声明定义了变量,变量存在的范围,主要是通过命名空间,来区分不同范围中声明的变量。作用域: 一个数据能够作用的范围

命名空间根据范围的不同,分为以下几种类型:

1.2 内建命名空间和内建作用域

Python程序中最大的一个命名空间,通常在解释器运行目标代码的时候(也就是点RUN的时候),由解释器创建的一个命名空间,负责初始化(即第一次赋值、第一次创建)系统环境变量。如:int/type()等

  • 内建命名空间加载时间:运行代码之前,通过解释器加载好系统的命名空间。包含了int/float/str/type()等等各种数据类型或者函数,所以我们在代码中才可以直接使用这些数据类型或者函数
  • 作用:初始化系统环境变量
  • 作用域:内建作用域(Builtin),此空间内的数据作用范围是整个内建空间,包括子空间
  • 查看方式:dir()

1.3 全局命名空间和全局作用域

定义: 编写Python代码时,创建一个python文件,其中声明在函数外部的变量,称为:全局变量(global)。当前可以声明全局变量的所有位置称为全局命名空间

加载时间:解释器运行目标代码时,加载全局命名空间,初始化该命名空间中的所有全局变量作用:声明、定义全局变量的范围作用域:全局作用(Global)查看方式:globals()查看当前全局命名空间中的所有全局变量,本质上globals()就是一个存储了数据的字典,

例如:

name = "张三"
age = 12
grade = ["1",2,"3"]
def outer():
    a = "a"
    def inner():
        a = "b"
    return inner
fun = outer()
fun()
print(f"全局变量字典为:{globals()}")

运行结果:

1.3 局部命名空间和局部作用域

定义:当Python文件中声明函数时,独立出来了一个小的作用范围(函数内部),通常情况下我们将函数内部的空间称为:局部命名空间

加载时间:解释器运行目标代码时,加载完全局命名空间之后,加载局部命名空间,初始化局部命名空间中的局部变量

注意:如果是嵌套函数,嵌套函数是没有命名空间的,嵌套函数的空间存于父函数内,但嵌套函数是有其自己的作用域的,叫嵌套作用域(内部作用域)

作用:声明、定义局部变量作用域:局部作用域(嵌套作用域)查看方式:Locals()查看当前命名空间中的所有数据

Locals(): 查看当前命名空间中的数据

编写在函数内部:查看局部命名空间中的数据编写在函数外部:和globals()一样的意义

示例:

name = "张三"
age = 12
grade = ["1",2,"3"]
def outer():
    a = "a"
    print(f"outer局部的数据:{locals()}")
    def inner():
        a = "b"
        print(f"inner局部的数据:{locals()}")
    return inner

fun = outer()
fun()
print(f"全局变量字典为:{globals()}")
print(f"全局部的数据:{locals()}")

运行结果:

1.4 总结

  • 命名空间是一个名词, 表示了一个可以声明变量的范围
  • 用作域是一个动词,表示一个变量起作用的范围
  • 解释器运行时,命名空间的加载顺序:内建命名空间–>全局命名空间–>局部命名空间
  • 查询使用变量,查询使用顺序:内部作用域–>嵌套作用域–>全局作用域–>内建作用域,也就是Python常说的LEGB原则。查找顺序通俗的说就是:就近原则,一直找到内建作用域,找不到报:“name is not defined”

1.5 扩展LEGB

  • Local,本地作用域,局部作用域的local命名空间。函数调用时创建,调用结束消亡
  • Enclosing,Python2.2时引入嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间
  • Global,全局作用域,即一个模块的命名空间。模块被import时创建 ,解释器退出时消亡
  • Build-in,内置模块的命名空间,生命周期从python解释器启动时创建到解释器退出时消亡,例如:print(open),print和open都是的变量

二、Global关键字的使用说明

在讲述什么是Global之前,让我们先来看一个例子,以下例子两条print语句分别打印什么:

x = 100
def fn1():
    x  =1
    print(f"函数内的{x}")
fn1()
print(f"变更后的{x}")

运行结果:

为什么会运行报错:X在使用前需要先分配变量值,明明我们在全局已经定义了一个X=100
原因:在python动态语言内,== 赋值即定义== ,在inner内部

  • x = 1其实是一个x = x 1的赋值语句,那这个x就会函数运行在初始化进行加载,变成局部的一个变量
  • 而=运算时,从左往右执行,在x=的时候已经默许了x是local variable,因此外部作用域的x=100是被屏蔽的。所以x 1中的x相当于一个没有赋值的变量,从而报错。

那么怎么解决这个问题?解决的办法一:使用global关建字将x定义为全局变量,这时在函数局部就会将x指向全局的变量x

让我们来看看具体的应用,下面的代码运行结果如何:

x = 100
def fn1():
    x = 10
    global x
    x  =1
    print(f"函数内的{x}")
fn1()
print(f"变更后的{x}")

运行结果:

为什么还是报错,我们不是已经使用了global吗?那是因为我们前面声明前加了一句:x = 10
x = 10 时会将其置为局部变量,但程序执行到global x时,发现x已经在局部定义过了,所以报错,所以我们要先声明再调用

所以我们将程序调整为:

那么问题又来了,下面的例子,global x在inner函数内可以调用吗?

x = 100
def outer():
    global x
    x  =1
    print(f"ouer的x调用结果{x}")
    def inner():
        x  =1
        print(f"inner的x调用结果{x}")
    return inner
a = outer()
a()

运行结果:

为什么报错,不是已经定义了global全局变量,同时也是局部作用域内先定义了吗?

原因:Global 定义只在全局和定义的当前作用域内起作用,所以上面的例子,global x只在全局作用域和嵌套作用域内可用,如果inner内部想调用,需要做以下调整

特别说明:

global关键字是一种破坏函数封装的方式,变量未经过传参即可在函数内部作用域内使用。所以在日常使用中,**不要使用,那我们要实现这种调用,可以用什么方式呢?python给我提供了一个关键字:Nolocal,后续我的笔记中会详细提到

到此这篇关于Python函数命名空间,作用域LEGB及Global详析的文章就介绍到这了,更多相关Python LEGB与Global内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Python函数命名空间,作用域LEGB及Global详析的更多相关文章

  1. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  2. ios – 不同作用域中相同命名常量的链接器错误

    我有一个名为“ID_KEY”的常量,它在3个单独的.m文件的顶部声明,其中没有包含其他文件.声明如下:而其他两个类也是如此.但是我收到一个链接器错误抱怨同名的多个定义.我的问题是为什么链接器抱怨这个呢?

  3. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  4. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  5. Swift、Go、Julia与R能否挑战 Python 的王者地位

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  6. 15.6 Swift局部引用

    /**局部引用和全局引用1.作用域2.生命周期*/varref:Int=Int.init/**定义一个变量或者常量,如果不是可选类型的话,一定要有初始值。所谓的局部引用就是在代码块里面的引用就是局部引用。作用域生命周期都在该代码块中;离它最近的括号*/iftrue{varref:Student=Student.initref.name="ZHangsan"}//超出作用域啦//ref.name="ZHangsan"

  7. 红薯因 Swift 重写开源中国失败,貌似欲改用 Python

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. 你没看错:Swift可以直接调用Python函数库

    上周Perfect又推出了新一轮服务器端Swift增强函数库:Perfect-Python。对,你没看错,在服务器端Swift其实可以轻松从其他语种的函数库中直接拿来调用,不需要修改任何内容。以如下python脚本为例:Perfect-Python可以用下列方法封装并调用以上函数,您所需要注意的仅仅是其函数名称以及参数。

  9. Swift中的列表解析

    在Swift中完成这个的最简单的方法是什么?我在寻找类似的东西:从Swift2.x开始,有一些与你的Python样式列表解析相当的东西。(在这个意义上,它更像是Python的xrange。如果你想保持集合懒惰一路通过,只是这样说:与Python中的列表解析语法不同,Swift中的这些操作遵循与其他操作相同的语法。

  10. swift抛出终端的python错误

    每当我尝试启动与python相关的swift时,我都会收到错误.我该如何解决?

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部