【问题标题】:How do you invoke a method on a programmatically set attribute?您如何在以编程方式设置的属性上调用方法?
【发布时间】:2018-03-27 16:54:14
【问题描述】:

这是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 问题。我可以想到其他可能想要调用属性上的方法的情况,该属性的名称被分配给一个字符串变量。我会很感激指导。

【问题讨论】:

  • 您应该有充分的理由拥有单独的aEntrybEntrycEntry 属性,而不是Entry 对象中的单个dict
  • 几乎从来没有一个很好的理由来为对象动态添加属性。更好的解决方案是使用字典来跟踪动态对象。如果您能阐明为什么您认为动态属性是您的问题的解决方案,那将会有所帮助。我们可以回答您提出的字面问题,但我怀疑这会让您更接近解决您的实际问题的正确解决方案,无论那是什么。

标签: python tkinter iterable setattr


【解决方案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)

【讨论】:

    【解决方案2】:

    要从字面上回答您提出的问题,您可以使用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
    

    【讨论】:

      猜你喜欢
      • 2021-05-20
      • 2021-06-22
      • 2023-01-03
      • 2012-08-20
      相关资源
      最近更新 更多