我有一个类,我发现自己多次定义相似的变量组,我相信如果我能够在循环中这样做更清楚,如下所示:
import tkinter as tk
from tkinter import ttk
class MyClass:
def __init__(self):
self.initializeVariables()
def initializeVariables(self):
varnames = ['a', 'b', 'c', 'd']
for var in varnames:
exec("self.bg{0} = ttk.Frame(self.Frame)".format(var))
exec("self.tb{0} = ttk.Entry(bg{0}, width=4)".format(var))
exec("self.tb{0}.grid(row=i)".format(var))
我有更多的元素,这个例子只是为了说明。我想知道:
exec
功能的情况下完成此操作?我试过globals()
,但没有成功答案 0 :(得分:3)
不需要为每个小部件设置单独的对象属性。在循环中创建属性会增加复杂性,而不会在这种情况下提供任何实际值。
我建议使用列表或字典来存储引用:
def initializeVariables(self):
varnames = ['a', 'b', 'c', 'd']
self.frames = {}
self.entries = {}
for var in varnames:
self.frames[var] = ttk.Frame(...)
self.entries[var] = ttk.Entry(...)
然后您可以通过他们的名字访问它们。例如:
self.entries["c"].get()
除非您需要访问代码其他部分的框架,否则可以使用框架的局部变量:
for var in varnames:
frame = tk.Frame(...)
self.entries[var] = ttk.Entry(frame, ...)
答案 1 :(得分:2)
您有几个选项远远优于exec
:
在给定属性的字符串名称的情况下,使用setattr()
function设置任意属性:
varnames = ['a', 'b', 'c', 'd']
for var in varnames:
frame = ttk.Frame(self.Frame)
entry = ttk.Entry(frame, width=4)
entry.grid(row=i)
setattr(self, 'bg{0}'.format(var), frame)
setattr(self, 'tb{0}'.format(var), entry)
使用vars(self)
作为字典访问实例名称空间:
namespace = vars(self)
varnames = ['a', 'b', 'c', 'd']
for var in varnames:
frame = ttk.Frame(self.Frame)
entry = ttk.Entry(frame, width=4)
entry.grid(row=i)
namespace['bg{0}'.format(var)] = frame
namespace['tb{0}'.format(var)] = entry
直接访问self.__dict__
命名空间:
varnames = ['a', 'b', 'c', 'd']
for var in varnames:
frame = ttk.Frame(self.Frame)
entry = ttk.Entry(frame, width=4)
entry.grid(row=i)
self.__dict__['bg{0}'.format(var)] = frame
self.__dict__['tb{0}'.format(var)] = entry
vars(self)
基本上是一种前向兼容且API友好的拼写方式self.__dict__
。我更喜欢使用setattr()
,因为这与使用__slots__
或挂钩__setattr__
的类兼容。
在循环中设置属性很好(甚至很好,因为你应用DRY principle),但使用exec
并不是最好的方法。
请考虑将字典或列表用于重复或分组的属性。字典或列表使得以后更容易访问go中的整个元素组:
frames = self.frames = {}
framed_entries = self.framed_entries = {}
varnames = ['a', 'b', 'c', 'd']
for var in varnames:
frame = ttk.Frame(self.Frame)
entry = ttk.Entry(frame, width=4)
entry.grid(row=i)
frames['bg{0}'.format(var)] = frame
framed_entries['tb{0}'.format(var)] = entry
现在,您可以通过字典上的简单循环访问这些相同的框架和条目,或者使用合适的密钥直接对每个框架和条目进行寻址。