图解python | 命名空间与作用域

简介: 命名空间与作用域是程序设计中的基础概念,深入理解有助于理解变量的生命周期,减少代码中的莫名其妙bug。

ShowMeAI研究中心

作者:韩信子@ShowMeAI
教程地址http://www.showmeai.tech/tutorials/56
本文地址http://www.showmeai.tech/article-detail/89
声明:版权所有,转载请联系平台与作者并注明出处


Python命名空间和作用域

命名空间与作用域是程序设计中的基础概念,深入理解有助于理解变量的生命周期,减少代码中的莫名其妙bug。

1.命名空间

命名空间,也称为Namespace、名称空间或名字空间,指的是从名字到对象的一个映射关系,类似于字典中的键值对,Python中很多命名空间的实现用的就是字典。

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

以电脑文件目录为例,一个文件夹中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。

Python 命名空间 / namespace

一般有三种命名空间:

  • 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
  • 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

3种命名空间(namespace)

  • 命名空间查找顺序:

假设我们要使用变量showmeai,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间

如果找不到变量showmeai,它将放弃查找并引发一个 NameError 异常:

NameError: name 'showmeai' is not defined。
  • 命名空间的生命周期

命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。

因此,我们无法从外部命名空间访问内部命名空间的对象。

num1 = 5
def some_func():
 
    # num2 是局部名称
    num2 = 6
    def some_inner_func():
 
        # num3 是内嵌的局部名称
        num3 = 7

如下图所示,相同的对象名称可以存在于多个命名空间中。

命名空间(namespace)的生命周期

2.作用域

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python 的作用域一共有4种,分别是:

  • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
  • G(Global):当前脚本的最外层,比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等,最后被搜索。

规则顺序: L –> E –> G –> B

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

Python 作用域

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。在Python3.x中,可以使用以下的代码来查看到底预定义了哪些变量:

>>> import builtins
>>> dir(builtins)

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:

>>> if True:
...  msg = 'I am a member of ShowMeAI'
... 
>>> msg
'I am a member of ShowMeAI'
>>> 

实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。

如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:

>>> def test():
...     msg_inner = 'I am a member of ShowMeAI'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>> 

从报错的信息上看,说明了 msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。

(1)全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下示例代码:

total = 0 # 这是一个全局变量
# 可写函数说明
def my_sum( arg1, arg2 ):
    #返回2个参数的和."
    total = arg1 + arg2 # total在这里是局部变量.
    print ("函数内是局部变量 : ", total)
    return total
 
#调用sum函数
my_sum( 10, 20 )
print("函数外是全局变量 : ", total)

以上实例输出结果:

函数内是局部变量 :  30
函数外是全局变量 :  0

(2)global和nonlocal关键字

当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。

以下示例代码修改全局变量 num:

num = 1
def my_func():
    global num  # 需要使用 global 关键字声明
    print(num) 
    num = 123
    print(num)
my_func()
print(num)

以上实例输出结果:

1
123
123

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:

def outer_num():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer_num()

以上示例输出结果:

100
100

另外有一种特殊情况,假设下面这段代码被运行:

a = 10
def test():
    a = a + 1
    print(a)
test()

以上程序执行,报错信息如下:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 5, in test
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

错误信息为局部作用域引用错误,因为 test 函数中的 a 使用的是局部,未定义,无法修改。

修改 a 为全局变量:

a = 10
def test_global():
    global a
    a = a + 1
    print(a)
test_global()

执行输出结果为:

11

也可以通过函数参数传递:

a = 10
def test_arg(a):
    a = a + 1
    print(a)
test_arg(a)

执行输出结果为:

11

3.视频教程

也可以点击 这里 到B站查看有【中英字幕】的版本

[video(video-Mw3yqM4p-1645638277447)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=505628451&page=16)(image-https://img-blog.csdnimg.cn/img_convert/6180c23b59334145a26b2fde30a69066.png)(title-【双语字幕+资料下载】Python 3全系列基础教程,全程代码演示&讲解!10小时视频42节,保证你能掌握Python!快来一起跟着视频敲代码~<快速入门系列>)]


资料与代码下载

本教程系列的代码可以在ShowMeAI对应的github中下载,可本地python环境运行,能访问Google的宝宝也可以直接借助google colab一键运行与交互操作学习哦!

本教程系列涉及的Python速查表可以在以下地址下载获取:

拓展参考资料

ShowMeAI相关文章推荐

ShowMeAI系列教程推荐

showmeai

目录
相关文章
|
2月前
|
存储 Python
在Python中,什么是作用域
【10月更文挑战第12天】在Python中,什么是作用域
29 2
|
3月前
|
Python
关于 Python 列表解析式的作用域问题
关于 Python 列表解析式的作用域问题
59 11
|
2月前
|
存储 自然语言处理 Python
解密 Python 的作用域和名字空间
解密 Python 的作用域和名字空间
27 1
|
4月前
|
Python
Python变量的作用域_参数类型_传递过程内存分析
理解Python中的变量作用域、参数类型和参数传递过程,对于编写高效和健壮的代码至关重要。正确的应用这些概念,有助于避免程序中的错误和内存泄漏。通过实践和经验积累,可以更好地理解Python的内存模型,并编写出更优质的代码。
38 2
|
4月前
|
Python
深入解析 Python中的命名空间和作用域并举例
【8月更文挑战第15天】Python中的命名空间与作用域是理解变量组织与访问的核心。命名空间是名称到对象的映射,分为全局、局部和内置三种。作用域定义变量的可访问范围,遵循LEGB规则:局部(L)、闭包(E)、全局(G)、内置(B)。示例展示了如何通过`nonlocal`声明跨作用域修改变量。这些机制确保了变量的有效管理和代码的高效执行。
53 0
|
4月前
|
存储 Python
Python中的命名空间
【8月更文挑战第8天】本文深入探讨了Python中命名空间与作用域的概念及其应用。命名空间管理变量名与对象间的映射关系,分为全局、局部及内建三种。全局命名空间包含模块顶层定义的变量,局部命名空间则由函数内部定义的变量构成,内建命名空间包括Python的所有内置函数与异常。作用域规定了变量的可见范围,包括全局、局部、嵌套及内建作用域。文章通过多个代码示例展示了不同作用域下的变量访问规则,如局部变量仅在函数内部有效,而全局变量可在整个模块中访问。此外,还介绍了作用域链的查找机制、如何通过`global`和`nonlocal`关键字修改不同作用域内的变量、如何利用闭包访问外部函数的局部变量。
|
6月前
|
Java Python
Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理
Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理
|
6月前
|
存储 Python
Python教程:深入理解Python中的命名空间和作用域
在 Python 编程中,理解命名空间(Namespace)和作用域(Scope)是至关重要的。它们决定了变量和函数的可见性和访问性,并直接影响代码的结构和行为。本文将深入探讨 Python 3 中命名空间和作用域的概念、规则以及相关的高级主题。
96 4
|
6月前
|
存储 Python
Python的命名空间和作用域分析
在Python中,命名空间(Namespace)是用来存储变量名和对象引用之间映射关系的字典,而作用域(Scope)是指程序中变量可以被访问的区域范围。Python中的命名空间是用来存储变量名和对象引用之间映射关系的字典,Python中存在3种命名空间:内置命名空间、全局命名空间和局部命名空间。Python中存在3种命名空间:内置命名空间、全局命名空间和局部命名空间。局部作用域:由局部命名空间定义,在函数内部定义的变量只能在该函数内部访问。在全局命名空间中定义的变量可以在模块内的任何函数或类中直接使用。
57 3
|
18天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!

热门文章

最新文章