初衷
在使用pytqt5开发车间生产良率分析的脚本UI时,需要按照不同产品呈现不同的良率曲线。
每种产品类型对应UI中的一个QCheckbox,通过QCheckbox勾选状态确定是否显示该产品的良率曲线如果但由于产品类型多,并且随时会添加新类型,每个类型又要添加对应的界面按钮,比较麻烦。
尝试用一个list集合,根据list集合动态生成对应的QCheckbox。
实现
通过查询资料,exec()作为python的内置函数,能够执行储存在字符串或文件中的python语句,动态地执行复杂python代码。eval()函数只能执行计算数学表达式的结果功能。
使用通配符创建类实例并赋值
list1 = ['PMSG066', 'PMSG076', 'PMP110']
for i in list1:
exec('step1_{} = TESTS({})'.format(i, i))报错
File "<string>", line 1, in <module>
NameError: name 'PMSG066' is not defined报错原理未知,和TESTS(i)动态创建实例有关。
尝试配合locals()局部变量实现
示例:
def f():
a = 0
exec("a = 1")
print(a)
def f2():
a = 0
exec("a = 1")
b = locals()['a']
print(b)
def f3():
exec("a = 1")
b = locals()['a']
print(b)
f()
f2()
f3()输出结果
0
0
1默认情况下,exec() 会在调用者局部和全局范围内执行代码。然而在函数里面, 传递给 exec()的局部范围,__在感知上是拷贝局部变量组成的一个字典__,如果 exec() 如果执行了修改操作,这种修改后的结果对实际局部变量值是没有影响的。
原理:
在CPython的源代码中,变量并非存在一个字典中,而是一个线性类似数组的集合,每一个变量赋予一个index,按顺序放进数组f_localsplus中。调用locals()方式实际上是将这个数组转换为dict并且返回。
在exec()函数的实现中,最终调用的是PyRun_StringFlags()或者PyRun_String(),运行代码时会新建一个frame,也就是exec()内执行的所有代码,都是在另外一个frame中运行的。
比如在f()中,第二行a = 0和第三行exec("a = 1")是在不同的frame里面运行的,虽然共享了一个locals()的dict,但是保存这两个a的局部变量位置不一样。当运行“a = 1”时,并不会修改外面原f函数frame保存的局部变量a。
但在函数外由于变量存在于globals的字典当中,就可以实现。
a = 0
exec("a = 1")
print(a)按照官方文档说明,我们应新建一个dict当作locals参数传入exec(),来获取对应的局部变量空间。
def f():
a =0
result = {}
exec("a = 1", globals(), result)
print(result)
print(a)输出结果
{'a': 1}
0最终实现代码:
class TESTS():
def __init__(self):
pass
class F():
def __init__(self):
list1 = ['PMSG066', 'PMSG076', 'PMP110']
result = {}
for i in list1:
exec('%s = TESTS()' %i, globals(), result)
setattr(self, 'step3_'+i, result[i])
test = F()参考资料:
[1] 【python】exec改不动局部变量?绝对触及你python知识区的盲点!_哔哩哔哩_bilibili
[2] 【笔记14】python动态创建对象(类实例)、动态赋值、动态生成变量_occamo的博客-CSDN博客
本文由 slocksu 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。