python中的内置globals()详解

最近在看一段代码时,发现作者使用globals()来应对无法确定变量名的情况,故此对该函数进行了详细的了解。

一、基本情况

globals() 是Python的标准内置函数,用于返回当前模块中定义的全局变量的字典(包含所有的全局变量、函数、类、导入的模块) ,其中键是变量名,值是变量的值。字典可进行修改,修改后会随之反映到全局变量上。对于函数内的代码,返回的为在定义函数时确定的该字典,无论在哪里调用都保持不变。

globals是特殊场景的解决方案,如动态批量处理全局变量/函数(eg:配置加载)、调试时快速排查全局状态问题、框架/库的底层实现,且有完善的封装和文档。
缺点:可读性差,命名冲突、作用域误区、线程不安全、性能损耗、破坏封装
重点:非必要不使用,优先使用字典/类进行替代,使用时做好校验、锁和注释。

二、常用场景实例
核心价值是动态操作全局命名空间 ,由于操作的是全局状态,使用时需要谨慎。

1、批量处理配置变量、根据配置变量名读取对应的值

python 复制代码
config0= 10
config1 = 30
config2 = "INFO"

# 变量名来自外部(如配置文件、用户输入)
config_keys = ["config0", "config1", "config2"]
# 动态读取所有配置
for key in config_keys:
    if key in globals():
        print(f"{key}: {globals()[key]}")

运行结果:

2、批量初始化

编码前,无法预知所有的变量名或需要生成大量相似的变量名,需要通过代码逻辑批量生成全局变量

3、函数内部修改全局变量

编码需要时,则需要使用,此处不进行举例说明了。

三、使用注意事项

globals()直接操作全局命名空间,滥用会导致代码可读性、可维护性大幅下降,甚至引发隐藏bug

1、严重降低代码可读性与可维护性

动态操作的变量/函数名是字符串,IDE无法自动补全、跳转,代码审查时难以追踪变量的定义/修改位置,后期维护成本高,如下图所示:

上方globals()里面变量/函数内容很多,某个变量随时可能被其他方法更改,当出现问题时,排查很困难。下方单独使用var_dict很清晰能知道变量是在哪里来的,在哪里修改的。

2、易引发命名冲突与意外覆盖

全局命名空间包含模块顶层定义的变量、函数、类等,globals()动态创建/修改变量,若名称与已有重复,则会静默覆盖原有对象。

在程序中,如不小心覆盖内置函数,在访问中可能会遇到报错,如下所示

在程序中,如多处动态给某个变量赋值,则会造成功能错误

如上所示,本身天津和重庆都有叫张三的,结果由于程序后面进行了覆盖,只保留了最后的值。这种在程序中也不存在语法错误,在排查bug时会比较麻烦
建议:动态命名时加前缀,避免与内置名、已有变量重名
操作赋值前,先校验是否为已有变量

3、globals()作用区域理解存在误区

python中的几种作用域可详见:https://blog.csdn.net/qq_44801116/article/details/158041678?spm=1001.2014.3001.5501

很多人会误以为globals()可以获取到外层函数作用域,实际是未搞清楚外层函数的变量的作用域为嵌套作用域,不会影响全局变量。嵌套函数想访问外层函数变量,需要使用nonlocal或local(),而非globals()

4、多线程时,存在线程安全问题

多线程同时通过globals()读写全局变量时,同时修改一个变量,会导致数据不一致。

python 复制代码
count = 0
def increment():
    for _ in range(100000):
        globals()["count"] += 1

t1 = threading.Thread(target=increment)
t2 = threading.Thread(target=increment)
t1.start()
t2.start()
t1.join()
t2.join()
print(count)

运行结果是200000,但是实际结果是随机,如下

可以通过加锁的形式,访问全局变量从而保证结果的正确性。

python 复制代码
def increment():
    for _ in range(100000):
        while threading.Lock():
            globals()["count"] += 1

5、性能损耗:尤其频繁操作

globals返回的字典,字典的键查找/赋值比直接访问变量要慢,尤其在频繁操作时会累积性能损耗。

建议循环中需要频繁操作局部变量时,先将赋值给局部变量,操作完成后再赋值给全局变量

相关推荐
悠哉清闲2 小时前
Future
java·开发语言·kotlin
weixin_440401692 小时前
Coze-智能体Agent(工作流:自定义插件+选择器+知识库检索+大模型润色)
python·ai·coze
Ulyanov2 小时前
基于Python的单脉冲雷达导引头回波生成技术
python·算法·仿真·单脉冲雷达、
deepxuan2 小时前
Day2--python三大库-numpy
开发语言·python·numpy
徐同保2 小时前
python如何手动抛出异常
java·前端·python
AD钙奶-lalala2 小时前
Android编译C++代码步骤详解
android·开发语言·c++
中科三方3 小时前
域名注册后无法解析解决方法:技术故障排查和解决指南
开发语言·github·php
极客先躯3 小时前
高级java每日一道面试题-2025年7月02日-基础篇[LangChain4j]-什么是 AiServices?它是如何简化 LLM 应用开发的?
java·开发语言
浅念-4 小时前
C++ :类和对象(4)
c语言·开发语言·c++·经验分享·笔记·学习·算法