如何在编程设置属性上调用方法?

时间:2018-03-27 16:54:14

标签: python tkinter iterable setattr

这是How do you programmatically set an attribute?的后续问题。

我看到如何使用setattr(x,attr,value)设置属性值。

我如何在attr上调用方法?

例如,我想创建和设置与字典相对应的Tkinter Entry对象的值,其中键是属性,值是要分配给属性的值。

我的蛮力方法有效:

from tkinter import Tk, Button, filedialog, Label, Frame, BOTH, Entry, END, StringVar


class Example(Frame):
    def __init__(self, master=None):
        """Initialize UI and set default values."""
        # https://stackoverflow.com/questions/285061/how-do-you-programmatically-set-an-attribute.

        Frame.__init__(self, master)
        self.master = master

        myDict = {'a': 'String A', 'b': 'String B', 'c': 'String C'}

        self.a = StringVar()
        self.a.set(myDict['a'])
        self.aEntry = Entry(self, textvariable=self.a)
        self.aEntry.grid(row=0, column=1)

        self.b = StringVar()
        self.b.set(myDict['b'])
        self.bEntry = Entry(self, textvariable=self.b)
        self.bEntry.grid(row=1, column=1)

        self.c = StringVar()
        self.c.set(myDict['c'])
        self.cEntry = Entry(self, textvariable=self.c)
        self.cEntry.grid(row=2, column=1)

        self.pack(fill=BOTH, expand=1)

root = Tk()
app = Example(root)
root.mainloop()

循环方法看起来像这样:

from tkinter import Tk, Button, filedialog, Label, Frame, BOTH, Entry, END, StringVar


class Example(Frame):
    def __init__(self, master=None):
        """Initialize UI and set default values."""
        # https://stackoverflow.com/questions/285061/how-do-you-programmatically-set-an-attribute.
        Frame.__init__(self, master)
        self.master = master

        myDict = {'a': 'String A', 'b': 'String B', 'c': 'String C'}

        rowCount = 0
        for key, value in myDict.items():
            setattr(self, key, StringVar()) # Works

            # self.a.set('String A')
            self.key.set(value) # Does not work

            # self.aEntry = Entry(self, textvariable=self.a)
            setattr(self, key + 'Entry', Entry(self, textvariable=???)) # Does not work

            # self.aEntry.grid(row=0, column=1)
            self.key + 'Entry'.grid(row=rowCount, column=1) # Does not work
            rowCount += 1

        self.pack(fill=BOTH, expand=1)


root = Tk()
app = Example(root)
root.mainloop()

如何重写标有“#不起作用”的行,以便循环工作?

这不仅仅是一个Tkinter问题。我可以想到其他情况,其中一个人可能想要在属性上调用一个方法,该方法的名称被赋给一个字符串变量。我很感激教练。

2 个答案:

答案 0 :(得分:1)

我不会为此使用单独的属性;我使用dict个关联的EntryStringVar对象。

getattrsetattr有自己的位置,但不能取代合理使用dict

class Example(Frame):
    def __init__(self, master=None):
        """Initialize UI and set default values."""
        # https://stackoverflow.com/questions/285061/how-do-you-programmatically-set-an-attribute.
        Frame.__init__(self, master)
        self.master = master

        myDict = {'a': 'String A', 'b': 'String B', 'c': 'String C'}

        self.entries = {}

        for rowCount, (key, value) in enumerate(myDict.items()):
            sv = StringVar()
            sv.set(value)

            e = Entry(self, textvariable=sv)
            e.grid(row=rowCount, column=1)

            self.entries[key] = (e, sv)

        self.pack(fill=BOTH, expand=1)

答案 1 :(得分:1)

要完全回答您提出的问题,您可以使用getattr获取对该属性的引用,此时您可以将其视为真实属性。

setattr(self, key, StringVar())
var = getattr(self, key)
var.set(...)

然而,这是一个坏主意。如果您使用字典来跟踪动态内容,您的代码将更容易编写,理解和修改。

例如:

rowCount = 0
self.vars = {}
self.entries = {}
for key, value in myDict.items():

    self.vars[key] = StringVar()
    self.vars[key].set(value)
    self.entries[key] = Entry(self, textvariable=self.vars[key])
    self.entries[key].grid(row=rowCount, column=1)
    rowCount += 1