python作用域与命名空间

命名空间和作用域是两个密切相关的概念,它们共同决定了如何查找变量名,以及变量在程序中的可见性和生命周期。

文章目录

  • 1. 简介
    • 1.1. 作用域
    • 1.2. 命名空间
    • 1.3. 联系与区别
      • 1.3.1. 例子
      • 1.3.2. 说明
  • 2. 命名空间
    • 2.1. 内置命名空间
    • 2.2. 全局命名空间
    • 2.3. 局部命名空间
    • 2.4. 类/对象命名空间
  • 3. 作用域
    • 3.1. 类别
      • 3.1.1. 局部作用域
      • 3.1.2. 嵌套作用域
      • 3.1.3. 全局作用域
      • 3.1.4. 内置作用域
    • 3.2. 变量查找顺序
    • 3.3. `global/nonlocal关键字`
  • 4. 示例
  • 5. 参考

1. 简介

1.1. 作用域

作用域是指程序中定义变量的区域,它决定了变量的可见范围以及它们的生命周期。在特定区域内定义的变量,不超出区域则变量可以被访问和使用,而超出这个区域,区域内定义的变量则不可被直接访问。

1.2. 命名空间

命名空间是用于存储和隔离标识符(如变量名、函数名等)的容器。每个命名空间都像一个字典,它将名字映射到相应的对象上。在Python中,每个作用域都拥有独立的命名空间,这允许相同的名字在不同的上下文中指向不同的对象,从而避免命名冲突。

1.3. 联系与区别

1.3.1. 例子

假设你在卧室(一个作用域,有一个命名空间)给手机充电,你可以使用卧室的插座(命名空间中的变量)。如果你需要使用客厅(另一个作用域,有另外一个命名空间)的插座(另一个命名空间的变量),你必须走到客厅去使用。在这个过程中,卧室和客厅的命名空间是独立的,但你的作用域(你的位置)决定了你可以直接访问哪些变量。

1.3.2. 说明

作用域决定了你在哪里可以使用哪些变量,而命名空间决定了这些变量是如何被隔离和存储的。通过上述例子,我们可以看到,卧室和客厅的命名空间是独立的,你的作用域(你的位置)决定了你可以直接访问哪些变量(命名空间中的东西)。

  • 作用域:关注于程序中变量的可访问性,它是一个动态的概念,取决于程序的执行位置。
  • 命名空间:关注于变量的存储和隔离,它是一个静态的概念,用于避免不同上下文中同名标识符的冲突。

2. 命名空间

命名空间是在不同时刻创建的,且拥有不同的生命周期。

2.1. 内置命名空间

内置名称的命名空间是在 Python 解释器启动时创建的,它包含了所有内建的函数和变量,例如abs()、print()、True和False。这个命名空间在整个解释器的生命周期内都是存在的,不会被删除。

2.2. 全局命名空间

模块的全局命名空间是在模块被读取时创建的。通常,这个命名空间会持续存在直到解释器退出。无论是从脚本文件中读取还是通过交互式解释器执行,所有的顶层代码都是__main__模块的一部分,__main__模块拥有自己的全局命名空间。值得注意的是,内置名称实际上也是模块的一部分,即builtins模块。

2.3. 局部命名空间

函数的局部命名空间是在函数被调用时创建的,并在函数执行完毕返回或在函数内部抛出未被捕获的异常时被删除。更准确地说,局部命名空间在函数执行结束后就不再被使用。每次函数的递归调用都会创建一个新的局部命名空间。

2.4. 类/对象命名空间

这些命名空间以属性集合的形式存在。类命名空间包含了类属性和类方法,而实例命名空间包含了实例属性和绑定到实例的方法。

3. 作用域

命名空间的作用域是Python代码中的一个特定文本区域,在这个区域内可以直接访问该命名空间中的变量和函数。当我们说“直接访问”,我们指的是在这个文本区域内,如果对一个名称进行非限定的引用(即不通过任何前缀或路径来指定名称的来源),Python会在包括该命名空间在内的范围内查找这个名称。简而言之,作用域决定了在特定代码段中可以访问哪些命名空间中的标识符。

3.1. 类别

3.1.1. 局部作用域

局部作用域是最小的作用域,通常在函数内部定义。在这个作用域中声明的变量只在该函数内部可见,被称为局部变量。当函数执行完毕后,这些局部变量就会消失,因为它们是随着函数调用的开始而创建,随着函数调用的结束而销毁的。

def my_function():
    local_var = "I am local"
    print(local_var)  # 可以访问 local_var

my_function()
# print(local_var)  # 这里会引发错误,因为 local_var 不在全局作用域中

3.1.2. 嵌套作用域

当一个函数定义在另一个函数内部时,就形成了嵌套作用域。在这种情况下,内部函数可以访问外部函数作用域中的变量,但外部函数不能访问内部函数作用域中的变量。这种特性使得内部函数可以继承外部函数的一些状态,而不影响全局作用域。

def outer_function():
    outer_var = "I am outer"

    def inner_function():
        inner_var = "I am inner"
        print(outer_var)  # 可以访问 outer_var
        print(inner_var)  # 可以访问 inner_var

    inner_function()
    # print(inner_var)  # 这里会引发错误,因为 inner_var 不在外部函数的作用域中

outer_function()
# print(inner_var)  # 这里会引发错误,因为 inner_var 不在全局作用域中
# print(outer_var)  # 这里会引发错误,因为 outer_var 不在全局作用域中

3.1.3. 全局作用域

全局作用域是最大的作用域,通常指在所有函数外部定义的变量。这些变量在整个程序中都是可见的,被称为全局变量。全局变量的生命周期是整个程序的执行过程,它们可以在程序的任何地方被访问和修改,除非它们被限定在某个局部作用域中。

global_var = "I am global"

def my_function():
    print(global_var)  # 可以访问 global_var

my_function()
print(global_var)

3.1.4. 内置作用域

内置作用域包含了Python解释器提供的一系列预定义的函数和变量,如len()、str()、range()等。这些内置函数和变量是Python语言的一部分,它们在任何Python程序中都是可用的,不需要额外的导入或定义。

print(len("Hello, World!"))  # 使用内置函数 len()
print(str(42))  # 使用内置函数 str()

3.2. 变量查找顺序

作用域虽然是被静态确定的,但会被动态使用。执行期间的任何时刻,都会有 3 或 4 个“命名空间可直接访问”的嵌套作用域:

  • 最内层作用域,包含局部名称,并首先在其中进行搜索
  • 那些外层闭包函数的作用域,包含“非局部、非全局”的名称,从最靠内层的那个作用域开始,逐层向外搜索。
  • 倒数第二层作用域,包含当前模块的全局名称
  • 最外层(最后搜索)的作用域,是内置名称的命名空间

3.3. global/nonlocal关键字

[[python-语句]]/语句

4. 示例

假设你的房子有多个房间(卧室、客厅、厨房),每个房间都有一些插座。这些插座可以看作是命名空间中的变量,而房间本身可以看作是作用域。

def house():
    def bedroom():
        plug = "bedroom plug"
        print("Charging in :", plug)

    def livingRoom():
        nonlocal plug
        plug = "living room phone"
        print("Charging in :", plug)

    def garden():
        global plug
        plug = "garden plug"
        print("Charging in garden:", plug)

    plug = "house plug"
    bedroom()
    print('-----------------------------')
    print("After bedroom charging:", plug)
    print('-----------------------------')
    livingRoom()
    print('-----------------------------')
    print("After living room charging:", plug)
    print('-----------------------------')
    garden()
    print('-----------------------------')
    print("After garden charging:", plug)
    print('-----------------------------')

house()
print("In global scope:", plug)
  • 输出:
Charging in : bedroom plug
-----------------------------
After bedroom charging: house plug
-----------------------------
Charging in : living room phone
-----------------------------
After living room charging: living room phone
-----------------------------
Charging in garden: garden plug
-----------------------------
After garden charging: living room phone
-----------------------------
In global scope: garden plug

5. 参考

python3.13.0教程

你可能感兴趣的:(Python,python,开发语言)