2

运行进行函数调用的程序时

self.getFileButton = Button(self,
                            text = "...",
                            command =
                            tkFileDialog.askopenfilename(mode="r+b", **self.file_opt))

我得到错误

File "C:/Documents and Settings/l/My Documents/Python/csv_GUI.py", line 33, in create_widgets
tkFileDialog.askopenfilename(mode="r+b", **self.file_opt))

AttributeError:selectFile 实例没有属性“file_opt”

4

3 回答 3

7

你可能想要这样的东西:

self.getFileButton = Button(self,
                            text = "...",
                            command = lambda: tkFileDialog.askopenfilename(mode="r+b", **self.file_opt))

问题在于,当您编写它时,该askopenfilename函数会在创建按钮时运行(而不是在单击时)。根据 AttributeError,您在创建file_opt映射之前创建按钮,但是,假设file_opt您单击按钮时属性存在,这应该将查找(和函数调用)推迟到适当的时间。

基本上,lambda只需创建一个新函数:

foo = lambda x : x*x

相当于*:

 def foo(x):
     return x*x

以这种方式编写,很容易理解为什么我们推迟调用askopenfilename函数,直到按钮实际被点击。

*在某些情况下,lambda 函数的行为与常规函数不同,但出于本文的目的,我们不必担心这些。

于 2012-12-13T19:19:04.203 回答
2

您实际上是否在您的方法或其他地方file_opt定义了一个成员?__init__

如果问题是你正在定义一个,但直到你完成之后getFileButton,你可以重新排列顺序吗?如果不是,mgilson 的解决方案是正确的。但除此之外,它要简单得多。

如果你在任何地方都没有file_opt成员,那就更简单了:不要试图传递不存在的东西。

于 2012-12-13T19:45:25.640 回答
1

我认为,一般来说,您应该避免在 Button 函数本身(使用 lambdas)中将参数传递给回调函数,这很丑陋,而且不是 pythonic。

改为执行以下操作:

def __init__(self, ...):
    ...
    Tkinter.Button(self, text='...', command=self.openfile).pack(...)
    ...

def openfile(self):
    return tkFileDialog.askopenfile(mode='r+b', **self.file_opt)

只是为了给出这个想法......

于 2012-12-13T19:40:22.573 回答