Python将字符串常量转化为变量方法总结

山海之间
山海之间
发布时间:2026-10-13| 4人浏览过
原创

本文探讨Python中将字符串常量动态转化为变量名的两种核心方法。通过修改全局命名空间(globals)和动态执行代码(exec),实现从字符串到变量的映射。文章详细解析了两种方案的原理、代码示例及注意事项,旨在解决动态生成变量名的技术难题,并引申出对eval与exec区别及安全性的讨论。

引言:动态生成变量名的挑战

日前,Python技术交流社群中M同学提出一个颇具趣味性的问题。经过初步探讨,大家普遍认为该问题难以直接解决。

但我认为此问题具有研究价值,值得深入思考解决方案,因此将其记录在私密的知识社区中。

出乎意料的是,次日便有两位社群成员接连提供了可行的解决思路。

这一事件在群内引发了热烈的技术探讨与交流。

本文对相关内容进行了梳理,并由此延伸出更深入的学习话题,期望能为读者提供有益参考。

问题背景:从常量到变量的转化

1、如何动态生成变量名?

M同学的具体问题如下:

打扰一下大家,请教一个问题,已知 list = ['A', 'B', 'C', 'D'] , 如何才能得到以 list 中元素命名的新列表 A = [], B = [], C = [], D = [] 呢?

简而言之,该问题的核心在于将字符串内容用作其他对象的变量名。

list中的元素为字符串,此处‘A'-‘D'属于常量,而目标结果中A-D需表现为变量。

若强行直接将常量当作变量使用,程序会抛出错误:

>>> 'A' = [] ...SyntaxError: can't assign to literal

报错信息中的literal指代字面量,这是计算机科学中的常见概念,用于表示源代码中的固定值。例如整数、浮点数、字符串等基本类型均属于字面量。

字面量代表一个量的本身,可理解为一种原子性实体,因此无法对其进行赋值操作。

因此,提取出的字符串内容不能直接作为变量名,必须寻找其他途径。

初学者可能会尝试list[0] = [],但这不可行,因为并未生成名为A的变量。若尝试A = list[0],接着A = [],同样行不通,因为这里的A是凭空定义的,而非从已有条件中动态生成的。

当时,群内仅有两三位同学参与讨论,我们未能找到解决办法。但我认为此题目颇具玩味价值。

若能解决此问题,意味着无需预先定义即可动态生成变量名,这不仅能减少命名负担,还能实现自动化编码!

可以设想未来,人工智能在编写代码时,若能根据已知条件动态生成变量名,编码过程将更加顺畅。(据悉,目前已有AI具备代码编写能力,不知其在变量命名时采用何种方法?)

解决方案一:修改全局命名空间

2、办法总是有的

近期,学习群中混入了一些广告发布者,为此我决定提高审核门槛,例如以群内问题作为考核标准。

出乎意料的是,首位被考核的Q同学几乎不假思索地提出了一个解决思路。巧合的是,几乎同时,群内J同学也给出了另一种解决方法(他未看到群内讨论,而是通过知识社区记录得知此问题)。

也就是说,前一晚看似无解的问题,在次日竟得到了两种不同的解决方案!

那么,他们的具体答案是什么呢?

globals()方法实现示例


# J 同学的解答
>>> list1 = ['A', 'B', 'C', 'D']
>>> for i in list1:
>>> globals()[i] = []
>>> A
[]

该方法通过修改全局命名空间,巧妙地“定义”出新变量。globals()方法返回一个字典,字符串‘A'作为其中一个键值(key),而该键值恰好对应全局命名空间中的一个变量,从而实现了从常量到变量的转化。

在数据结构层面,空列表[]作为值(value)与字符串键值绑定;在应用层面,它作为变量内容与变量名绑定。

看到此回答时,我突然想起上个月转载过一篇《Python 动态赋值的陷阱》,讲述的正是动态变量赋值问题!我此前似乎只关注了globals()与locals()用法的区别,并未真正掌握它们的原始用途。

J同学表示,他正是通过阅读那篇文章习得此方法。这很有趣:我分享了一个自己一知半解的知识,随后被J同学吸收掌握,最终反馈回来解决了我的难题。

我深切感受到知识分享的魅力:知识在流动中获得生命,在碰撞中熠熠生辉。

同时,我也深刻体会到互助学习团体的益处:利人者利己,互助者共同进步。

解决方案二:动态执行代码

3、动态执行代码的方法

新加入群的Q同学提供了另一种答案:

exec()与f-strings应用示例


# Q 同学的解答
>>> list1 = ['A', 'B', 'C', 'D']
>>> for i in list1:
>>> exec(f"{i} = []")
>>> A
[]

他的写法利用了Python 3.6引入的f-strings特性。事实上,在较低版本中也可实现,只需确保exec()方法接收的参数是包含变量i的字符串即可,例如这样写:

兼容低版本的字符串拼接写法


# 以下代码可替换上例的第 4 行
exec(i + " = []")
# 或者:
exec("{} = []".format(i))
# 或者:
exec(' '.join([i, '= []']))

这几种写法的区别仅在于字符串拼接方式,关于如何拼接字符串以及不同方法间的区别,可参考《详解Python拼接字符串的七种方式》。

Q同学答案的核心在于exec()方法,它是Python内置函数,用于执行存储在字符串或文件中的代码段。

其基础用法如下:

exec()基础用法说明


>>> exec('x = 1 + 2')
>>> x
3

# 执行代码段
>>> s = """
>>> x = 10
>>> y = 20
>>> sum = x + y
>>> print(sum)
>>> """
>>> exec(s)
30

了解exec()用法后,我们再回顾Q同学的答案。for循环中提取的i为字符串,拼接后的字符串经exec()处理,便获得了动态编写代码的效果。

也就是说,因字符串常量的内容被当作有效代码执行,其中的'A'-'D'元素便获得了新身份,转化为最终的A-D变量名。

该方法看似简单,但由于exec()方法较为生僻,直到Q同学提出,我们才恍然大悟。

注意:在Python3中,exec()是内置方法;而在Python2中,exec是语句(statement),另有execfile()方法,两者合并后形成Python3中的exec()。本文基于Python3编写。

总结与延伸讨论

4、总结

抽象最初的问题,其实际询问的是“如何将字符串内容作为其他对象的变量名”,更进一步讲是——“如何将常量转化为变量”。

使用直接赋值的静态方法行不通。

两位同学提出的方法均为间接动态方法:一是动态进行变量赋值,通过修改命名空间植入变量;二是动态执行代码,可谓通过“走后门”的方式安插变量。

两种方法殊途同归,无论白猫黑猫,只要抓到老鼠就是好猫。

这两种方法已带来极具价值的启发,并促使群内伙伴发散讨论相关话题,例如:S同学提出另一种修改命名空间中变量的写法、L同学提及eval()的意义、eval()与exec()的区别、我查阅了为何慎用eval()、C与H同学探讨了eval()的安全用法……

尽管某些话题无法在群聊中充分展开,但这些话题知识的延展联系,极大丰富了本文开头的问题。这一个微小问题,牵连出两个大的知识体系。

最后,真诚感谢群内这些爱学习的优秀同志们!除文中提及者外,还有其他同学做出积极贡献,大家表现都非常给力!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。