2017-01-10 5 views
4

Ich möchte eine Mathematik-App für Grundschulkinder (Kinder im Alter von 4-11) machen, und ich habe damit begonnen, einen Taschenrechner zu machen. Ich befolge ein YouTube-Video, aber es wird ein Fehler angezeigt. Ich schreibe übrigens in Python 3.4.3.Probleme mit Python Rechner

Dies ist mein Code:

from tkinter import* 

def iCalc(source, side): 
    storeObj = Frame(source, borderwidth=4, bd=4,bg="pink") 
    storeObj.pack(side=side, expand=YES, fill=BOTH) 
    return storeObj 

def button (source, side, text, command=None): 
    storeObj = Button(source, text=text, command=command) 
    storeObj.pack(side=side, expand=YES, fill=BOTH) 
    return storeObj 

class app(Frame): 
    def __init__(self): 
     Frame.__init__(self) 
     self.option_add('*Font', 'arial 20 bold') 
     self.pack(expand=YES, fill=BOTH) 
     self.master.title('Calculator') 


     display = StringVar() 
     Entry(self, relief=RIDGE, 
       textvariable=display,justify='right' ,bd=30,bg="pink").pack(side=TOP, expand=YES, 
                      fill=BOTH) 
     for clearBut in (["CE"],["C"]): 
      erase = iCalc(self, TOP) 
      for ichar in clearBut: 
       button(erase, LEFT, ichar, 
         lambda storeObj=display, q=ichar: storeObj.set('')) 

     for NumBut in ("789 /" , "456*" , "123-", "0.+"): 
      FunctionNum = iCalc(self, TOP) 
      for iEquals in NumBut: 
       button(FunctionNum, LEFT, iEquals, 
         lambda storeObj=display, q=iEquals: storeObj.set(storeObj.get() + q)) 

     EqualsButton = iCalc(self, TOP) 
     for iEquals in "=": 
      if iEquals == '=': 
       btniEquals = button(EqualsButton, LEFT, iEquals) 
       btniEquals.bind('<ButtonRelease-1>', 
           lambda e, s=self, storeObj=display: s.calc(storeObj), '+') 
      else: 
       btniEquals = button(EqualsButton, LEFT, iEquals, 
        lambda storeObj=display, s=' %s '%iEquals: storeObj.set(storeObj.get()+s)) 


      def calc(self, display): 
       try: 
        display.set(eval(display.get())) 
       except: 
        display.set("ERROR") 



if __name__ == '__main__': 
    app().mainloop() 

Und das ist der Fehler, der nach oben hält, zeigt:

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__ 
    return self.func(*args) 
    File "C:\Users\sony\Documents\Raeesa Calc.py", line 42, in <lambda> 
    lambda e, s=self, storeObj=display: s.calc(storeObj), '+') 
AttributeError: 'app' object has no attribute 'calc' 

Was bedeuten diese Fehler?

+1

den Einzug – depperm

+0

Leider beheben, wenn ich ein wenig albern klingen, aber bitte könnten Sie mir sagen, was die Vertiefung ist? –

+3

Python verwendet Einrückung (Abstand) zum Parsen, und zur Zeit ist 'calc' zu weit eingerückt (oder hat zu viele Leerzeichen) – depperm

Antwort

3

s ist ein App Objekt. Ihre App Klasse hat keine Methode calc. Die einzige Erscheinung dieses Namens ist innerhalb einer für Schleife innerhalb __init__. Wenn das eine Klassenmethode sein soll, müssen Sie sie nach links auf die richtige Einrückungsebene ziehen: löschen Sie genügend Leerzeichen, dass es vertikal unter "def init" liegt.

Auch, was versuchst du mit diesem Code zu tun?

for iEquals in "=": 
    if iEquals == '=': 

Die für Schleife hat genau einen Wert in der Iteration Satz, die muss sein, ein Gleichheitszeichen. Warum haben Sie eine für durch ein konstantes Element durchlaufen und dann Test um zu sehen, ob das, was Sie haben? Eine einfache Zeile wird das gleiche tun:

iEquals = '=' 
0

Ich habe einige Ihrer Probleme hier behoben. Zum Teil sind Sie nicht zum Abmessen gewöhnt, aber Sie hatten definitiv einige Fehler. Siehe meine Kommentare:

import ast 
# Honestly you should do `import tkinter as tk`, 
# but it's not that bad. 
from tkinter import * 

# this should be named something different, 
# maybe something like `wrap_widget`. Also note 
# snake_casing instead of camelCasing. Python avoids 
# camelCasing, and uses StudlyCase for classes, and 
# snake_casing_for_everything_else. 
def iCalc(source, side): 
    storeObj = Frame(source, borderwidth=4, bd=4,bg="pink") 
    storeObj.pack(side=side, expand=YES, fill=BOTH) 
    return storeObj 

def button(source, side, text, command=None): 
    storeObj = Button(source, text=text, command=command) 
    storeObj.pack(side=side, expand=YES, fill=BOTH) 
    return storeObj 

# Should be `App`. You could also just inherit from `tk.Tk`, which is 
# a toplevel window. 
class app(Frame): 
    def __init__(self): 
     Frame.__init__(self) 
     self.option_add('*Font', 'arial 20 bold') 
     self.pack(expand=YES, fill=BOTH) 
     self.master.title('Calculator') 

     display = StringVar() 
     # Just further wrapped your line 
     Entry(self, 
       relief=RIDGE, 
       textvariable=display, 
       justify='right', 
       bd=30, 
       bg="pink").pack(side=TOP, expand=YES, fill=BOTH) 

     # There was no need for looping over single element lists. 
     # Also `button_text` is a more accurate name. 
     for button_text in ("CE", "C"): 
      erase = iCalc(self, TOP) 
      button(erase, LEFT, button_text, 
        lambda storeObj=display, q=button_text: storeObj.set('')) 

     # row is a better name here, as you're looping over 
     # rows of button (texts) 
     for row in ("789 /" , "456*" , "123-", "0.+"): 
      FunctionNum = iCalc(self, TOP) 
      # renamed button_text here, too. 
      for button_text in row: 
       button(FunctionNum, LEFT, button_text, 
         lambda storeObj=display, q=button_text: storeObj.set(storeObj.get() + q)) 

     EqualsButton = iCalc(self, TOP) 
     # as others have mentioned you really shouldn't loop over the single element string. 
     # I'm assuming you plan to add other characters in here. If not, 
     # get rid of the extra code! 
     for iEquals in "=": 
      if iEquals == '=': 
       btniEquals = button(EqualsButton, LEFT, iEquals) 
       btniEquals.bind('<ButtonRelease-1>', 
           lambda e, s=self, storeObj=display: s.calc(storeObj), '+') 
      else: 
       btniEquals = button(EqualsButton, LEFT, iEquals, 
        lambda storeObj=display, s=' %s '%iEquals: storeObj.set(storeObj.get()+s)) 

    # This was indented *way* too much. That's why it wasn't defined. 
    def calc(self, display): 
     try: 
      # I uses `ast.literal_eval`, as there are less security risks. 
      # And for maths, there's really no reason to need anything else. 
      display.set(ast.literal_eval(display.get())) 
     except: 
      display.set("ERROR") 


if __name__ == '__main__': 
    app().mainloop()