I am writing a calculator with using kivy even flooded the githabs https://github.com/maqstein/calculator I was allergic to repeat the code, I decided to implement this by iterating through the values ​​in the dictionary, but when I start counting or clearing the label the program crashes. functions separately work. the problem is not them

import time from kivy.app import App from kivy.uix.button import Button from kivy.config import Config from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.label import Label Config.set('graphics', 'resizable', 0) Config.set('graphics', 'height', 400) Config.set('graphics', 'width', 300) class MyApp(App): def calculate(self): try: self.formula = str(eval(self.label.text)) except ZeroDivisionError: self.formula="opening a black hole" # TODO: open a black hole here self.update_label() def clear_label(self, instance): self.formula = '0' self.update_label() def update_label(self): self.label.text = self.formula def add_a_thing(self, instance): if self.formula == "0": self.formula = "" self.formula += str(instance.text) self.update_label() def build(self): # some crutch here self.label = Label(text='0', font_size=40, halign='right', text_size=(295, 100), size_hint=(1, 0.4)) self.formula = '0' box_layout = BoxLayout(orientation='vertical') grid_layout = GridLayout(rows=5, cols=4) box_layout.add_widget(self.label) # magic for i in self.operations: if not bool(self.operations[i]): # if there is no value in dictionary this will be False(cause of not it will be True) grid_layout.add_widget(Button(text=f"{i}",on_press=self.add_a_thing)) else: grid_layout.add_widget(Button(text=f"{i}",on_press=self.operations[i])) box_layout.add_widget(grid_layout) return box_layout operations ={ '%':'', '/':'', '*':'', '-':'', '7':'', '8':'', '9':'', '+':'', '4':'', '5':'', '6':'', 'Clr':clear_label, '1':'', '2':'', '3':'', '=':calculate, '':'', '0':'', '.':'', '':'', } if __name__ == "__main__": MyApp().run() 

here is an error trying to clean the label

 Traceback (most recent call last): File "C:/Users/maq/PycharmProjects/explorer/main.py", line 82, in <module> MyApp().run() File "C:\Program Files\Python37\lib\site-packages\kivy\app.py", line 826, in run runTouchApp() File "C:\Program Files\Python37\lib\site-packages\kivy\base.py", line 502, in runTouchApp EventLoop.window.mainloop() File "C:\Program Files\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 727, in mainloop self._mainloop() File "C:\Program Files\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 460, in _mainloop EventLoop.idle() File "C:\Program Files\Python37\lib\site-packages\kivy\base.py", line 340, in idle self.dispatch_input() File "C:\Program Files\Python37\lib\site-packages\kivy\base.py", line 325, in dispatch_input post_dispatch_input(*pop(0)) File "C:\Program Files\Python37\lib\site-packages\kivy\base.py", line 231, in post_dispatch_input listener.dispatch('on_motion', etype, me) File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch File "C:\Program Files\Python37\lib\site-packages\kivy\core\window\__init__.py", line 1360, in on_motion self.dispatch('on_touch_down', me) File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch File "C:\Program Files\Python37\lib\site-packages\kivy\core\window\__init__.py", line 1376, in on_touch_down if w.dispatch('on_touch_down', touch): File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch File "C:\Program Files\Python37\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down if child.dispatch('on_touch_down', touch): File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch File "C:\Program Files\Python37\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down if child.dispatch('on_touch_down', touch): File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch File "C:\Program Files\Python37\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down self.dispatch('on_press') File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch File "kivy\_event.pyx", line 1138, in kivy._event.EventObservers._dispatch File "C:/Users/maq/PycharmProjects/explorer/main.py", line 21, in calculate self.formula = str(eval(self.label.text)) AttributeError: 'Button' object has no attribute 'label' 

PS I know about the kivy markup language, but I want to implement my calculator in this way.

  • You do not understand the error text? - Enikeyschik

1 answer 1

self.add_a_thing is a related method, when called, self is automatically passed as a first argument.

calculete in operations is just a function, it expects self , i.e. MyApp, and gets an instance type Button .

OOP in python rather peculiar, declarations within a class are not related to any particular instance, only to the class itself, and instances can see them because of the hierarchical search for names both in the instance and in the class and in its ancestors.

In short, something specific to the instance will have to be initialized inside the class method, and the methods will be linked only (almost only) when they explicitly specify an instance variable before them.

Repetition of the code is not good, but the explicit one always looks better than the implicit, it’s me about empty fields in the dictionary, which means add_a_thing . Look for a compromise.