Python has a set of rules for how documentation strings should look like. These strings are called docstring
s in Python and the corresponding PEP is PEP257. You basically just move your comments from above the function name inside and make them strings:
def display(self):
"""Calls the visible features."""
self.top = Tk()
self.labels()
self.entries()
self.buttons()
# must remain at bottom or wont be displayed
self.top.mainloop()
Python also has an official style-guide, PEP8, which recommends adding a single space after the #
in a comment, as well as using a single blank line between class methods (and two between class or normal function definitions). It also recommends using a space after a comma in an argument list, but no spaces surrounding =
for keyword arguments.
Your method display
could be moved completely to the __init__
, but it is also fine as a separate method, in case you ever want to call it again to reset your application / display it again after changing some values. I would swap the display
and labels
methods, though, it makes for easier reading.
Regarding your doubt if you are overusing self
, i think you are rather underusing it than overusing. I'm not exactly sure how Tkinter
handles objects, but in Python in general, objects can and will be garbage-collected once they go outside of scope. So, after e.g. the method labels
ran, the local variable x_coord_label
will be removed and the associated object deleted (unless it is still being referenced from somewhere else, like the Tk
main loop for example). So I would store these labels/buttons etc also as class members. This is handy if you ever want to modify them as well (changing the text label on a button is a quite regular feature...).
In general, you should avoid using from X import *
, because it clutters your global namespace and might lead to name conflicts. With Tkinter
, many people use it anyway, mostly because one tends to use a lot of its functions, so selectively importing from TKinter import Button, Label, ...
becomes too long and unreadable and always writing Tkinter.Button
is also quite verbose. As a compromise you can use import Tkinter as tk
, which is shorter and still has its own namespace.
Final code:
import Tkinter as tk
class MainFrame(object):
def __init__(self):
self.display()
def display(self):
"""Calls the visible features."""
self.top = tk.Tk()
self.labels()
self.entries()
self.buttons()
# must remain at bottom or wont be displayed
self.top.mainloop()
def labels(self):
"""Display all the labels for the main frame."""
# adding x-cord label
self.x_cord_label = tk.Label(
self.top, text='X-Coordinate').grid(row=0, column=0)
def entries(self):
"""Display all the entry boxes for the main frame."""
self.x_cord_entry = tk.Entry(self.top, bd=5).grid(row=0, column=1)
def buttons(self):
self.x_cord_button = tk.Button(
self.top, text='Enter').grid(row=0, column=2)
If you want to extend this further, you probably want to add more than one button. In this case, you will need to decide on a datastructure to hold your texts and buttons. So in the end it might look more like this:
class MainFrame(object):
def __init__(self, button_texts):
self.button_texts = button_texts
self.top = tk.Tk()
self.setup_rows()
self.top.mainloop()
def setup_rows(self):
"""
Display all the rows with labels, entries and buttons
for the main frame.
"""
self.rows = []
top = self.top
for i, text in enumerate(self.button_texts):
row = [tk.Label(top, text=text).grid(row=i, column=0),
tk.Entry(top, bd=5).grid(row=i, column=1),
tk.Button(top, text='Enter').grid(row=i, column=2)]
self.rows.append(row)