小蝌蚪找妈妈:Python之作用域链与 LEGB 原则

news2024/11/14 15:22:08

文章目录

  • 参考
  • 描述
  • 作用域对象
      • 全局作用域
          • globals()
      • 局部作用域
          • locals()
      • 包含作用域
      • 内置作用域
          • builtins 模块
            • builtins 模块与 \_\_builtins__
            • builtins is \_\_builtins__???
          • \_\_builtins__ 与内置作用域
          • 赶不走的 \_\_builtins__
  • 作用域链
      • 作用域链 与 LEGB 原则
      • 狗急跳墙之法

参考

项目描述
Python 官方文档builtins.html
搜索引擎Google 、Bing

描述

项目描述
PyCharm2023.1 (Professional Edition)
Python3.10.6

作用域对象

作用域对象(Scope Object)是一个在 Python 中 用于管理命名空间的内部数据结构,它是 Python 解释器在执行代码期间维护和使用的重要组成部分。

每当创建一个新的函数、类或模块时,Python 解释器都会创建一个相应的作用域对象来跟踪该作用域内的变量、函数和其他命名项。作用域对象形成了一个层次结构,这样有利于按照特定的规则进行变量和命名空间的查找和访问。

作用域对象主要起如下作用:

项目描述
命名空间作用域对象维护一个命名空间,用于存储在该作用域中定义的变量、函数和其他命名项。命名空间 可以看作是一个 字典,其中 是名称, 是与名称关联的对象。
变量查找当在作用域中引用一个变量时,Python 解释器会按照 特定的规则 在作用域对象的命名空间中查找该变量。
命名冲突解决作用域对象帮助解决同一作用域中可能存在的命名冲突问题,确保每个名称在其命名空间中是唯一的。当在作用域中定义了 多个同名的变量或函数 时,作用域对象确保每个名称在其命名空间中是 唯一的,以避免混淆和错误。
作用域链 作用域对象通过构建一个 嵌套的链表结构 来实现变量和命名空间的查找。该链表按照 特定的顺序 链接了所有嵌套的作用域对象,使得解释器能够按照规定的顺序在不同的作用域中进行查找。
作用域切换当程序执行流进入或离开一个作用域时,作用域对象负责管理当前活动作用域的状态。作用域对象将在程序执行流进入作用域时被创建并在其离开作用域时进行清理,以确保 正确的命名空间的访问生命周期管理

全局作用域

全局作用域(Global Scope)是指在整个程序中可见的、位于 模块级别 的作用域。它是在模块中定义的变量、函数和类的作用域范围。

在Python中,全局作用域(Global Scope)指的是在 整个程序中 可见的、位于 模块级别 的作用域。全局作用域包含了在 全局范围内 定义的变量、函数、类和其他命名项。全局作用域是程序启动时创建的,一直存在 于整个程序的执行过程中。
全局作用域与 Python 中的 模块 密切相关。每个 Python 文件 都可以看作是一个模块,模块具有自己的全局作用域。在模块中定义的全局变量和函数可以在整个模块中访问和使用。

globals()

globals() 是一个内置函数,它返回一个 表示当前模块全局命名空间的字典,该字典存储了当前模块中定义的所有全局变量和函数。

举个栗子

free_var = 'Hello World'

# globals() 在程序的任何位置访问的结果都是
# 一致的。
for name in globals().copy():
    print(f'{name}\t{globals()[name]}')


# 在调用 globals() 函数时,MyClass
# 与 func 都尚未添加到全局命名空间中。
# 仅但解释器执行到 MyClass 与 func 的定义部分
# Python 才会将其添加至全局命名空间。
class MyClass:
    pass


print()
print('MyClass' in globals())
print('func' in globals())
print()


def func():
    pass


print('MyClass' in globals())
print('func' in globals())

执行效果

当解释器加载一个 模块(任何 Python 文件都可被视为模块) 时,它首先会创建一个新的全局作用域对象,用于存储该模块的全局变量、函数、类和其他定义。解释器会 按顺序解析 模块中的代码,并在执行过程中 将标识符绑定到相应的作用域对象中

__name__	__main__
__doc__	None
__package__	None
__loader__	<_frozen_importlib_external.SourceFileLoader object at 0x000002868F414820>
__spec__	None
__annotations__	{}
__builtins__	<module 'builtins' (built-in)>
__file__	C:\Users\RedHeart\PycharmProjects\pythonProject\example.py
__cached__	None
free_var	Hello World

True
False

True
True

局部作用域

Python 中,每当函数被调用时,都会为其创建一个新的局部作用域对象。这意味着 每个函数 都有自己的 独立的 局部作用域,其中定义的变量只在函数执行期间存在,当 函数返回时,局部作用域及其变量都会被 销毁
局部作用域提供了一种封装变量的机制,使得它们不会与其他函数或全局作用域中的变量发生冲突。这有助于提高代码的可读性、可维护性和重用性。

locals()

在 Python 中,locals() 是一个内置函数,用于返回 当前作用域 中的局部变量和其对应的值的字典,其中键是变量名,值是对应变量的值。对此,请参考如下示例:

# 当在全局作用域中调用 locals() 函数时,
# 该函数将返回全局命名空间字典,与 globals()
# 返回的值相同。
print(locals() == globals())


def func():
    # 当在函数中调用 locals() 函数时,
    # 该函数将返回其所在函数的局部命名空间字典。
    local_var = 'Hello World'
    print(locals())


func()

执行效果

True
{'local_var': 'Hello World'}

包含作用域

当在一个局部作用域内部定义了另一个作用域(例如,在函数内部定义了另一个函数),就产生了包含作用域。在相互嵌套的函数级作用域中,最内层的作用域被称为局部作用域,其他作用域被称为包含作用域。

举个栗子

# 全局作用域
def external_func():
    # 包含作用域
    def middle_func():
        # 包含作用域
        def internal_func():
            # 局部作用域
            pass

内置作用域

在 Python 中,内置作用域(Built-in Scope)指的是 Python 解释器预先定义的一组函数和变量,它们可以在任何地方直接使用,无需导入其他模块。

内置作用域中包含了一些常用的对象(如 print()len()range()True 等),用于执行各种常见的任务和操作。这些对象可以被 所有 的 Python 代码 直接访问,而 无需显式地导入任何模块

builtins 模块

在Python中,builtins 模块是一个内置模块,它包含了 Python 的内置函数、异常和其他一些内置对象。这个模块将在 Python 解释器启动时自动加载,因此你可以直接访问其中定义的对象,而无需显式导入。

builtins模块提供了许多常用的内置函数和内置对象,例如:

  • print():用于输出文本到控制台。
  • input():用于从控制台读取用户输入。
  • len():用于获取对象的长度。
  • int()float()str() 等类型转换函数。
  • ExceptionTypeErrorValueError 等异常类。
  • abs()round()min()max() 等常用函数。
builtins 模块与 __builtins__

在 Python 中,__builtins__ 是一个特殊的全局变量,它指向一个字典,其中包含了内置函数、异常和对象的名称空间。在模块的全局作用域中,可以通过 __builtins__ 来访问这些内置函数和对象。

当使用 import builtins 导入 builtins 模块时,builtins 模块本身会被加载并创建一个模块对象。然后,模块对象的 __dict____dict__属性是一个字典,用于存储对象的实例变量和方法)属性会被用于初始化 __builtins__ 变量,使其指向 builtins 模块的名称空间。

因此,可以说 __builtins__builtins 模块导入至模块中的结果。通过__builtins__,可以在模块中访问到 builtins 模块提供的内置函数和对象,例如 __builtins__.print()__builtins__.len() 等。

builtins is __builtins__???

在 Python 中,多次导入同一模块的情况下,实际上只会执行一次模块的加载和初始化过程。之后的导入操作会直接引用已经加载的模块对象,而不会再次执行模块内的代码。

这意味着,多次导入同一模块并不会导致模块内的代码被重复执行。只有在第一次导入时,模块内的代码才会被执行一次,并且模块对象会被创建。之后的导入操作将简单地引用已经加载的模块对象。

Python 解释器会在运行 Python 文件时自动导入 builtins 模块,显式导入 builtins 模块将直接引用已加载的 builtins 模块对象。因此,builtins is __builtins__ 的结果将为 True

__builtins__ 与内置作用域

在 Python 中,内置作用域对象可以通过访问全局变量 __builtins__ 来进行访问。__builtins__ 是一个特殊的全局变量,它指向一个模块对象,该模块对象包含了 Python 的内置对象。

赶不走的 __builtins__

在 Python 中,导入的模块可以通过 __del__ 关键字进行删除。对此,请参考如下示例:

# 判断 sys 模块是否已经被导入
print('sys' in globals())

# 导入 sys 模块
import sys

print('sys' in globals())

# 尝试使用 del 关键字删除已导入模块 sys
del sys

print('sys' in globals())

执行效果

False
True
False

但对于 Python 自动导入至全局作用域的 builtins 对象来说,你是无法通过任何方式将其删除的。这是因为,builtins解释器的一部分,它是在解释器启动时创建的,并且在整个解释器的生命周期中保持不变。因此,我们不能通过常规的方法来删除或修改 builtins
你可以删除或修改 Python 提供的内置作用域对象的全局变量形式 __builtins__,但这并不会导致 Python 解释器无法使用 builtins 模块提供的基础部件。对此,请参考如下示例:

print('__builtins__' in globals())

# 尝试使用 del 关键字删除 __builtins__ 变量
del __builtins__

# 仍然可以使用 print()、globals() 及 in 等内置对象
print('__builtins__' in globals())

作用域链

作用域链 与 LEGB 原则

LEGB 原则作用域链(Scope chain)和是密切相关的概念,用于描述变量查找和访问的顺序。
LEGB 是指 Python 中对象查找的四个层次,分别是局部作用域、包含作用域、全局作用域以及内置作用域。

作用域链是描述变量查找的顺序,它根据 LEGB 原则形成。当在代码中引用一个对象时,Python 会 按照 LEGB 的顺序进行对象的查找,直到找到 第一个匹配 的变量。

下面是一个示例,展示了作用域链和 LEGB 原则的应用:

# 内置作用域中定义的变量
__builtins__.k = 40

# 全局作用域中定义的变量
x = 10

def outer():
    # 包含作用域中定义的变量
    y = 20

    def inner():
        # 局部作用域中定义的变量
        z = 30
        # 由于在局部作用域中查找到了变量 y,
        # 故不再沿着作用域链查找 y 的值,故 y = 30。
        y = 30
        # 10 + 30 + 30 + 40 = 110
        print(x + y + z + k)

    inner()


outer()

执行效果

110

狗急跳墙之法

LEGB 原则 可知,当除内置作用域外的其他作用域中若存在与内置对象同名的对象时,内置对象将被其他同名对象所 遮盖
在 Python 中,当存在同名的对象覆盖了 Python 提供的内置对象时,可以使用 __builtins__ 来引用原始的内置对象。对此,请参考如下示例:

def print(content):
    pass


# 内置对象 print() 已被全局作用域中的同名函数 print() 所遮盖
print('Hello World')

# 通过使用 __builtins__ 全局变量访问直接访问内置对象
__builtins__.print('Hello China')

执行效果

Hello China

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/564630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Go语言从入门到实战】基础篇

Go语言从入门到实战 — 基础篇 First Go Program 编译 & 运行 基本程序结构 应用程序入口 package mainimport "fmt"func main() {fmt.Println("Hello World") }退出返回值 package mainimport ("fmt""os" )func main() {fmt.Pr…

哪个产品功能重要?KANO模型帮你

哪个产品功能重要&#xff1f;KANO模型来帮你 模型工具可以协助思考和系统化改进 KANO模型是小日本一个教授提出 趣讲大白话&#xff1a;往往&#xff0c;怎么思考&#xff0c;比思考什么重要 【趣讲信息科技175期】 **************************** 东京理工大学教授狩野纪昭(No…

【医学图像】图像分割系列.2 (diffusion)

介绍几篇使用diffusion来实现医学图像分割的论文&#xff1a;DARL&#xff08;ICLR2023&#xff09;&#xff0c;MedSegDiff&#xff08;MIDL2023&#xff09;& MedSegDiff-V2&#xff08;arXiv2023&#xff09;&#xff0c;ImgX-DiffSeg&#xff08;arXiv2023&#xff09;…

CTF 2015: Search Engine-fastbin_dup_into_stack

参考&#xff1a; [1]https://gsgx.me/posts/9447-ctf-2015-search-engine-writeup/ [2]https://blog.csdn.net/weixin_38419913/article/details/103238963(掌握利用点&#xff0c;省略各种逆向细节) [3]https://bbs.kanxue.com/thread-267876.htm&#xff08;逆向调试详解&am…

web功能测试方法大全—完整!全面!(纯干货,建议收藏哦~)

本文通过六个部分为大家梳理了web功能测试过程中&#xff0c;容易出现的遗漏的部分&#xff0c;用以发掘自己工作中的疏漏。&#xff08;纯干货&#xff0c;建议收藏哦~&#xff09; 一、输入框 1、字符型输入框 2、数值型输入框 3、日期型输入框 4、信息重复 在一些需要命…

GPT-4版Windows炸场,整个系统就是一个对话机器人,微软开建AI全宇宙

原创 智东西编辑部 智东西 Windows的GPT时刻到来&#xff0c;变革PC行业。 作者 | 智东西编辑部 今日凌晨&#xff0c;Windows迎来了GPT-4时刻&#xff01; 在2023微软Build大会上&#xff0c;微软总裁萨蒂亚纳德拉&#xff08;Satya Nadella&#xff09;宣布推出Windows Co…

实现免杀:Shellcode的AES和XOR加密策略(vt查杀率:4/70)

前言 什么是私钥和公钥 私钥和公钥是密码学中用于实现加密、解密和数字签名等功能的关键组件。 私钥是一种加密算法中的秘密密钥&#xff0c;只有密钥的拥有者可以访问和使用它。私钥通常用于数字签名和数据加密等场景中&#xff0c;它可以用于对数据进行加密&#xff0c;同…

头部效应凸显,消金行业迈入“巨头赛”?

回顾已经过去的2022年&#xff0c;消金行业面临着来自多方面的考验&#xff0c;承压前行&#xff0c;而随着进入2023年&#xff0c;相关企业也陆续展示出过去一年的发展成果&#xff0c;以此为后续发展做出指引。 当前&#xff0c;30家已开业的消金公司中&#xff0c;29家的20…

《消息队列高手课》课程笔记(三)

如何利用事务消息实现分布式事务&#xff1f; 什么是分布式事务&#xff1f; 消息队列中的“事务”&#xff0c;主要解决的是消息生产者和消息消费者的数据一致性问题。如果我们需要对若干数据进行更新操作&#xff0c;为了保证这些数据的完整性和一致性&#xff0c;我们希望…

独立站怎么搭建?搭建一个独立站的10个建议和步骤

要搭建一个独立站&#xff08;也称为个人网站或博客&#xff09;&#xff0c;以下是一些建议和步骤&#xff1a; 选择一个合适的域名&#xff1a;选择一个简洁、易记且与您网站内容相关的域名。确保域名可用&#xff0c;并注册该域名。 寻找一个合适的主机服务提供商&#xff…

【Cpp】哈希之手撕闭散列/开散列

文章目录 unorderedunordered系列关联式容器unordered_map和unordered_set概述unordered_map的文档介绍unordered_map的接口说明 底层结构 哈希哈希/散列表 概念哈希冲突哈希函数哈希函数设计原则&#xff1a;常见哈希函数 哈希冲突解决闭散列线性探测二次探测 开散列 哈希表的…

C语言数据结构——树、堆(堆排序)、TOPK问题

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;数据结构 &#x1f525;座右铭&#xff1a;“不要等到什么都没…

使用go语言构建区块链 Part4.事务1

英文源地址 简介 事务是比特币的核心, 区块链的唯一目的是以安全可靠的方式存储交易, 因此在交易创建后没有人可以修改. 今天我们开始实现事务, 但由于这是一个相当大的主题, 我将它分成两部分: 在这一部分中, 我们将实现事务的通用机制, 在第二部分中, 我们将研究细节. 此外…

让你在Windows打开Sketch格式再也不愁

Sketch是Macos的专用矢量绘图应用。在Sketch软件中&#xff0c;ios开发者可以轻松设计图层面板等图层的常用操作&#xff0c;广泛应用于产品的交互设计和UI设计&#xff0c;帮助很多设计师创作出很多优秀的作品。然而&#xff0c;Sketch只服务于Macos系统&#xff0c;这使得许多…

Laravel框架06:文件、迁移填充、会话、缓存

Laravel框架06&#xff1a;文件、迁移填充、会话、缓存 一、文件上传1. 文件上传表单2. 上传业务处理3. 全部代码 二、数据表的迁移与填充1. 迁移文件① 创建迁移文件② 编写迁移文件③ 执行迁移文件④ 回滚迁移文件 2. 填充&#xff08;种子&#xff09;文件① 创建填充文件②…

C++常用的支持中文的GUI库Qt 6之三: Qt 6的项目的发布

C常用的支持中文的GUI库Qt 6之三&#xff1a; Qt 6的项目的发布 本文接着上一篇“C常用的支持中文的GUI库Qt 6之二&#xff1a;项目的结构、资源文件的使用” https://blog.csdn.net/cnds123/article/details/130741807介绍&#xff0c;并使用其中的例子。 程序代码能正确编译…

【STL】list的使用

系列文章 学习C途中自然绕不过STL&#xff0c;在这个系列文章之中 我们讲了string的使用和string的模拟实现&#xff0c;以及vector的使用、vector的模拟实现。 感兴趣的可以翻翻看。 目录 系列文章 前言 默认成员函数 构造函数 拷贝构造 赋值重载 迭代器 容量查询 …

人人都能看懂的Spring源码解析,Spring声明式事务关于传播特性、事务挂起与恢复的处理

人人都能看懂的Spring源码解析&#xff0c;Spring声明式事务关于传播特性、事务挂起与恢复的处理 原理解析AbstractPlatformTransactionManager事务传播特性事务挂起与恢复通过DataSourceTransactionManager看事务挂起和恢复的具体实现 代码走读总结 往期文章&#xff1a; 人人…

LRU Cache

前言 哈喽&#xff0c;各位小伙伴大家好&#xff0c;本章内容为大家介绍计算机当中为了提高数据相互传输时的效率而引进的一种重要设计结构叫做LRU Cache,下面将为大家详细介绍什么是LRU Cache,以及它是如何是实现的&#xff0c;如何提升效率的。 1.什么是LRU Cache? LRU是L…

卷起来了?2023这三个项目直接让你原地起飞!

理论自学谁不会&#xff0c;理论知识跟实战项目实践相结合才是大问题&#xff1f; 还在发愁没有项目练手&#xff1f;还在发愁简历中的项目生搬硬凑&#xff1f;还在担心自己没实操过项目被面试官直接K.O? 这三个实战项目让你快人一步&#xff0c;总有一个适合你的&#xff…