Python 中用列表中的字符串元素作为名字来创建新变量
问题的提出
今天我在写一个与计算化学相关的某个 Python 脚本的时候,突然有了一个这样的疑问:
如果给定一个列表(list) a; 已知该列表中的元素均为字符串(str); 列表中元素的个数 n 以及作为列表元素的这些字符串的值都是不预知的; 那么,如何以这些列表元素作为变量名称来批量创建 n 个新变量呢? 以创建 n 个新列表为例。
于是我开始在 V2mm 的群以及其他小伙伴的群里面求助,得到了以 River 和 Xuanwo 等技术流的指点。总结如下:
用类实现
这两种方法是 River 提供的。
方法1 静态类型
a = ['r','e','m']
class Test():
def __init__(self,a = ['r','e','m']):
for item in a:
setattr(self, item, [])
Test(a)
方法2 动态类型
a = ['r','e','m']
MyClass = type('MyClass', (), {i: [] for i in a})
print(MyClass().r, MyClass().e,MyClass().m) # [] [] []
用字典
这种方法是 FlagPlus 提供的思路;
a = ['r','e','m']
tmp={}
for item in a:
tmp.update({item:[]})
River 给出了精简的建议:
a = ['r','e','m']
m=({k: [] for k in a})
用类加字典
这种方法是我基于 FlagPlus 提供的思路自己乱写的。
a = ['r','e','m']
class Test2():
tmp={}
def __init__(self,a = ['r','e','m']):
self.a=a
for item in self.a:
self.tmp.update({item:[]})
Test2(a)
用 locals 来添加变量
这两种方法是 River 提供的,用 globals 应该也可以。 River 不推荐这种方法,因为这样可能污染 module 的命名空间。
a = ['r','e','m']
for x in test:
locals()[x] = []
用函数来封装一下:
a = ['r','e','m']
def func(mylist):
for x in mylist:
locals()[x] = []
func(a)
用 exec 直接将字符串来执行
这个思路来自 Kivy 群的 X_Tu,应该是最简单直接地解决了问题。
a = ['r','e','m']
for i in a :
exec(i+'=[]')
Xuanwo 不推荐这样做,变量创建会造成性能开销,因为存在栈上而不是堆上。
River 对此表示存疑:
堆和栈和“exec” 这个关键字无关,和你在哪里调用 exec 有关。 其实一个变量在堆上还是在栈上和你的程序上下文有关,不是那么简单。我们都知道闭包就是保存在堆上的,而普通的函数内部变量都在栈上。
exec 可以接受额外两个参数,一个代表 locals, 一个代表 globals. 如果 locals 在栈上,生成的变量应该在栈上个,如果 locals 在堆上,生成的变量应该在堆上。待我研究一下,久未搞 c/c++,有点搞不清了
范神 推荐对复杂数据使用数据库,数据库操作时间是毫秒级,会更快一些。说的数据库是毫秒级,毫秒级是慢的,CPU都是低于微秒的,所以他不推荐用数据库。。。。