2014-08-29 53 views
0

我正在制作一个基本的GUI应用程序,使用tkinter收集用户输入来填充docx模板。 代码太多,所以我只会发布我认为是问题的地方。这是我的按钮。参数不会通过

self.my_button = Button(self.master, text="Create the Contract", 
          command=lambda: self.create_contract(self.name_entry.get(), 
                   self.address_entry.get(), 
                   self.city_entry.get(), 
                   self.postal_code_entry.get(), 
                   self.phone_entry.get(), 
                   self.email_entry.get(), 
                   self.arrival_entry.get(), 
                   self.departure_entry.get(), 
                   self.total_nights_entry.get(), 
                   self.before_tax_entry.get(), 
                   self.total_nights_entry.get(), 
                   calculations.gst(self.before_tax_entry.get()), 
                   calculations.tvq(self.before_tax_entry.get()), 
                   calculations.minitax(self.before_tax_entry.get()) 
                   )) 

    self.my_button.grid(row=10, column=0) 

    self.master.mainloop() 

def create_contract(self, name, address, city, postal_code, phone, email, arrival, departure, before_tax, total_nights, gst_tax, tvq_tax, mini_tax): 
    contract_template.CreateContract(name, address, city, postal_code, phone, email, arrival, departure, before_tax, total_nights, gst_tax, tvq_tax, mini_tax) 

算了一笔账:

def gst(before_tax): 
    guest_gst = int(before_tax) * 0.05 
    return guest_gst 

def tvq(before_tax): 
    guest_tvq = int(before_tax) * 0.09975 
    return guest_tvq 

def minitax(total_nights): 
    guest_minitax = int(total_nights) * 2 
    return guest_minitax 

现在,当我运行的应用程序,该GUI被显示出来,我有我的所有条目和按钮,但是当我点击该按钮:

>>> import GUIcontract 
Exception in Tkinter callback 
Traceback (most recent call last): 
    File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__ 
    return self.func(*args) 
    File "GUIcontract.py", line 76, in <lambda> 
    calculations.minitax(self.before_tax_entry.get()) 
TypeError: create_contract() takes exactly 14 arguments (15 given) 
>>> 

我一直在这个过去的8个小时。我希望我的笔记本电脑更坚固,所以我可以扔掉它。 问题显然是

calculations.minitax(self.before_tax_entry.get()) 
+1

再看看你传递的参数。有一个奇怪的。 – user2357112 2014-08-29 02:48:23

+2

你正在传递'self.total_nights_entry.get()'两次...... – mgilson 2014-08-29 02:49:53

回答

4

简单的解决方法是不以这种方式使用lambda。你让事情太难了。由于所有这些变量都是对象上的属性,因此可以在回调中获取它们。没有理由将它们传递给函数。

self.my_button = Button(..., command=self.create_contract) 
... 
def create_contract(self): 
    name = self.name_entry.get() 
    address = self.address_entry.get() 
    ... 

最终结果是一样的,但代码更易于理解和管理。长的参数列表容易出现这种常见的错误(传递错误的参数数量),所以最好尽可能避免长参数列表。

一个很好的经验法则是如果你必须传递多个参数,永远不要使用lambda表达式。

+1

问题不在于'lambda'(尽管Guido对此深感憎恨),它的事实是任何*函数都有2或3个以上论点,在我看来。匿名函数与常规函数没有什么不同 - 如果您曾经写过一个包含许多参数的函数(除了在某些特殊情况下(例如处理来自某个您无法控制的地方的输入),则出现了一些问题。 – 2014-08-29 02:57:56

+1

这是非常好的建议。任何时候你的函数有超过4或5个参数,值得考虑是否可以修改。 (编辑:意见明显不同,在哪里画线,但一般原则是太多的参数==需要重构的函数。) – rmunn 2014-08-29 02:58:32

+0

同意它是非常混乱。有什么方法可以减少函数中的大量参数?用更多功能稀释? @Bryan Oakley – z82n 2014-08-29 03:06:00

3

你传递一个额外的参数内

command=lambda: self.create_contract(self.name_entry.get(), 
                   self.address_entry.get(), 
                   self.city_entry.get(), 
                   self.postal_code_entry.get(), 
                   self.phone_entry.get(), 
                   self.email_entry.get(), 
                   self.arrival_entry.get(), 
                   self.departure_entry.get(), 
                   self.total_nights_entry.get(), 
                   self.before_tax_entry.get(), 
                   self.total_nights_entry.get(), 
                   calculations.gst(self.before_tax_entry.get()), 
                   calculations.tvq(self.before_tax_entry.get()), 
                   calculations.minitax(self.before_tax_entry.get()) 
                   )) 

你声明的函数有14个参数(包括self),但你传递15(再次,包括self)。我不知道哪一个是额外的,因为用15个参数来阅读函数是非常困难的。你应该强烈地,强烈地考虑重构这个,以便它不再有15个参数。查看Builder模式,或者参数模式。

编辑:显然,额外的参数是

self.total_nights_entry.get(), 
self.before_tax_entry.get(),  
self.total_nights_entry.get(), 

在评论中指出的mgilson。

0
def create_contract(self, name, address, city, postal_code, phone, email, arrival, departure, before_tax, total_nights, gst_tax, tvq_tax, mini_tax): 
  1. 自,2.姓名,地址3,4城市,5. POSTAL_CODE,6.电话,电子邮件7. 8.到达,离开9. 10. before_tax,11. total_nights ,12。gst_tax,13。tvq_tax,14。mini_tax

create_contract需要14个参数,包括自我。

self.create_contract(
    1. self.name_entry.get(), 
    2. self.address_entry.get(), 
    3. self.city_entry.get(), 
    4. self.postal_code_entry.get(), 
    5. self.phone_entry.get(), 
    6. self.email_entry.get(), 
    7. self.arrival_entry.get(), 
    8. self.departure_entry.get(), 
    9. self.total_nights_entry.get(), 
    10. self.before_tax_entry.get(), 
    11. self.total_nights_entry.get(), 
    12. calculations.gst(self.before_tax_entry.get()), 
    13. calculations.tvq(self.before_tax_entry.get()), 
    14. calculations.minitax(self.before_tax_entry.get()) 
) 

create_contract被通过14 args不包括自我。

0
在按钮

self.total_nights_entry.get() 

被调用两次