This is a life counter that I am using together with my friends for card games (Magic the Gathering).For those who know the game, it is actually designed for 1vs1 Commander.It provides you with the possibility to take notes about life points, commander damage, and also to roll a dice to decide who has to start the game.I would like to know if it is well written (in a Pythonic way) or if there is something that I can learn from the community to improve my sintax and my coding style: in fact, I am new to Python and to coding (to give you an idea of my level, I have started writing this app 1 month ago, and actually I code 2-3 hours a week).Please note that the functions set_20, set_30, set_40 are not actually called from the interface: in a future version there will be a settings section (that is why there is also a Settings screen at the end of the builder) but I am still working on it.Despite what is written in the above paragraph, the app works correctly: I am writing it following the Agile methodology, so I am adding pieces of functions/code when I have an idea without compromising the functionality of the app.If you wish, you could also follow the project on Github: the code below is in the v2 branch, the master contains the first version of the app.from kivy.app import Appfrom kivy.uix.boxlayout import BoxLayoutfrom kivy.properties import NumericPropertyfrom kivy.uix.textinput import TextInputfrom kivy.lang import Builderimport randomBuilder.load_string('''<LifeCounter>:    ScreenManager:        size_hint: 20, 1        id: _screen_manager        Screen:            name: 'MainScreen'            BoxLayout:                 orientation: 'vertical'                padding: 50                FloatLayout:                    orientation: 'horizontal'                    Button:                        text: Me                        font_size: '20sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .4, .6                        on_release: root.change_name(self)                    Button:                        text: Opponent                        font_size: '20sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .4, .6                        on_release: root.change_name(self)                FloatLayout:                    orientation: 'horizontal'                    Label:                        id: l_label                        font_size: '40sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .4, .8                        text: str(root.count)                        canvas.before:                             Color:                                 rgb: .6, .6, .6                             Rectangle:                                 pos: self.pos                                 size: self.size                     Label:                        id: l_label2                        font_size: '40sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .4, .8                        text: str(root.count2)                        canvas.before:                             Color:                                 rgb: .6, .6, .6                             Rectangle:                                 pos: self.pos                                 size: self.size                 FloatLayout:                    orientation: 'horizontal'                    Button:                        text: -                        font_size: '30sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .2, .8                        on_release: root.decr()                     Button:                        text: +                        font_size: '30sp'                        pos_hint: {'x':.20, 'y':.3}                        size_hint: .2, .8                        on_release: root.incr()                         Button:                        text: -                        font_size: '30sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .2, .8                        on_release: root.decr2()                    Button:                        text: +                        font_size: '30sp'                        pos_hint: {'x':.75, 'y':.3}                        size_hint: .2, .8                        on_release: root.incr2()                FloatLayout:                    orientation: 'horizontal'                    Button:                        text: Commander A                        font_size: '20sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .4, .8                        on_release: root.change_name(self)                    Button:                        text: Commander B                        font_size: '20sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .4, .8                        on_release: root.change_name(self)                FloatLayout:                    orientation: 'horizontal'                    Label:                        id: l_label                        font_size: '40sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .4, .8                        text: str(root.cmdcount)                        canvas.before:                             Color:                                 rgb: .6, .6, .6                             Rectangle:                                 pos: self.pos                                 size: self.size                     Label:                        id: l_label2                        font_size: '40sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .4, .8                        text: str(root.cmdcount2)                        canvas.before:                             Color:                                 rgb: .6, .6, .6                             Rectangle:                                 pos: self.pos                                 size: self.size                 FloatLayout:                    orientation: 'horizontal'                    Button:                        text: -                        font_size: '30sp'                        pos_hint: {'x':.0, 'y':.3}                        size_hint: .2, .8                        on_release: root.decrcmd()                      Button:                        text: +                        font_size: '30sp'                        pos_hint: {'x':.20, 'y':.3}                        size_hint: .2, .8                        on_release: root.incrcmd()                          Button:                        text: -                        font_size: '30sp'                        pos_hint: {'x':.55, 'y':.3}                        size_hint: .2, .8                        on_release: root.decrcmd2()                    Button:                        text: +                        font_size: '30sp'                        pos_hint: {'x':.75, 'y':.3}                        size_hint: .2, .8                        on_release: root.incrcmd2()                FloatLayout:                    orientation: 'horizontal'                    Button:                        text: Roll a dice                        pos_hint: {'x':.0, 'y':.005}                        size_hint: .4, .8                        font_size: '20sp'                        on_release: root.roll_dice()                    Label:                        text: str(root.dice)                        pos_hint: {'x':.55, 'y':.005}                        size_hint: .4, .8                        font_size: '20sp'                        canvas.before:                             Color:                                 rgb: .6, .6, .6                             Rectangle:                                 pos: self.pos                                 size: self.size                FloatLayout:                    orientation: 'horizontal'                    Button:                        text: -->                        pos_hint: {'x':.65, 'y': .0}                        size_hint: .3, .8                        on_release: pass        Screen:            name: 'Settings'            BoxLayout:                 orientation: 'vertical'                padding: 50                FloatLayout:                    orientation: 'horizontal'                    Button:                        text: 20                        pos_hint: {'x':.12, 'y':.6}                        size_hint: .2, .5                        font_size: '20sp'                        on_release: root.set_20()                    Button:                        text: 30                        pos_hint: {'x':.40, 'y':.6}                        size_hint: .2, .5                        font_size: '20sp'                        on_release: root.set_30()                    Button:                        text: 40                        pos_hint: {'x':.68, 'y':.6}                        size_hint: .2, .5                        font_size: '20sp'                        on_release: root.set_40()''')class LifeCounter(BoxLayout):    count = NumericProperty(30)    count2 = NumericProperty(30)    cmdcount = NumericProperty(0)    cmdcount2 = NumericProperty(0)    dice = NumericProperty(0)    def __init__(self, **kwargs):        super(LifeCounter, self).__init__(**kwargs)        self.hide_input = TextInput(size_hint=(None, None),                                    size=(0, 0),                                    multiline=False)        self.hide_input_bind = None    # The functions below update the names of the players and of the commanders.    def change_name(self, instance):        if self.hide_input_bind:            self.hide_input.unbind_uid('text',                                       self.hide_input_bind)        self.hide_input.text = instance.text        self.hide_input.focus = True        self.hide_input_bind = self.hide_input.fbind('text',                                                     self._update_text,                                                     instance)    def _update_text(self, button,                     instance, value):        button.text = value    # The functions below update the labels of the player's life points.    def incr(self):        self.count += 1    def decr(self):        self.count -= 1    def incr2(self):        self.count2 += 1    def decr2(self):        self.count2 -= 1    # The functions below update the labels of the commander damage.    def incrcmd(self):        self.cmdcount += 1    def decrcmd(self):        self.cmdcount -= 1    def incrcmd2(self):        self.cmdcount2 += 1    def decrcmd2(self):        self.cmdcount2 -= 1    # The functions below set the lifepoints to 20, 30, 40 according to user's needs.    def set_20(self):        self.count = 20        self.count2 = 20    def set_30(self):        self.count = 30        self.count2 = 30    def set_40(self):        self.count = 40        self.count2 = 40    # The function below rolls the dice    def roll_dice(self):        self.min = 1        self.max = 20        self.dice = random.randint(self.min,                                   self.max)class MtgLifeCounter(App):    def build(self):        return LifeCounter()if __name__ == '__main__':    MtgLifeCounter().run()
Life Counter for Magic the Gathering
python;kivy
Don't use fields unnecessarilyThe self.min and self.max values are not used anywhere else in the posted code outside of this function:def roll_dice(self):    self.min = 1    self.max = 20    self.dice = random.randint(self.min,                               self.max)So they should not be fields, local variables would be enough:def roll_dice(self):    min, max = 1, 20    self.dice = random.randint(min, max)And why use local variables at all when you can simply write:def roll_dice(self):    self.dice = random.randint(1, 20)Don't repeat yourselfThese functions have the same behavior, just use different numbers:def set_20(self):    self.count = 20    self.count2 = 20def set_30(self):    self.count = 30    self.count2 = 30It would be better to add a helper function  and reuse that:def set_20(self):    self.set(20)def set_30(self):    self.set(30)def _set(self, value):    self.count = value    self.count2 = valueFormattingWhy write like this:def _update_text(self, button,                 instance, value):    button.text = valueWhen you can write more naturally as:def _update_text(self, button, instance, value):    button.text = value