Tkinter Frames - Classes - python

So I'm using tkinter to make a GUI and at the moment I have several different frames. The way I programmed it is by just using one massive class but everywhere I look online (like here - https://pythonprogramming.net/change-show-new-frame-tkinter/), people are using a new class for every single "page". Is what I am doing wrong/not efficient or is it fine?
Unfortunately I cannot show my code as it's for a CA but the below is similar:
class App(tk.Frame):
def __init__(self):
tk.Frame.__init(self)
self.PageOne()
def PageOne(self):
coding stuff
def PageTwo(self):
pass

What you are doing is probably fine. I say "probably" because it depends on many factors which you haven't explained in your question.
The tutorial you referenced came from a stackoverflow answer that was explicitly addressing how to switch between two frames. It's not necessarily a recommended way to code, it's simply one of many ways.
That being said, if you have distinct pages then you might find it easier to manage your code if each page was a self-contained object. Doing so gives each page its own namespace, so you don't have to worry that one page is accidentally modifying the data that belongs to some other page. Plus, for larger projects it allows you to implement each page in a separate file so you don't end up with one huge file full of code.
Since not all GUIs are oriented around the concept of pages, this technique isn't a one-size-fits-all solution. It's OK to make each page a class, it's also OK to create each page via a function. The choice depends on many variables, such as your comfort with working with classes, the size of your project, the type of UI you're creating, and so on.

Related

Python: Same or different method names in MVC

I am currently writing a booking system and I'm following MVC.
My question is what is considered a better practice:
All methods from the different packages along the line of a single operation to have the same names
Come up with different names for each method?
To clarify my questions, here is an example:
When booking an appointment, that's the current sequence:
The toplevel windows calls root.book_appointment() (root is the "controller" of the view package)
root calls controller.book_appointment()
controller calls model.book_appointment()
model calls database.book_appointment()
I tried to find a convention or opinions somewhere, but I could not find anything.
One way, everything has the same names, even though there is always an identifier before the method call(root, controller, model, database etc). On the other hand for every operation that starts from a panel I need to come up with another 5 method names until I reach the database.
Thanks a lot in advance for your time and answers!
Tried googling for answers, but nothing came up. Most answers were for methods with same names and different parameters.

Splitting code into modules (conventions)

So I've been searching for a bit and couldn't find anything on Google or PEP discussing this.
I am doing a project with tkinter and I had a file, that is part of a project, that was only 200 lines of code (excluding all the commented out code). While the entire file was related to the GUI portion of the project, it felt a bit long and a bit broad to me.
I ended up splitting the file into 4 different files that each has its own portion of the GUI.
Basically, the directory looks like this:
project/
guiclasses/
statisticsframe.py
textframes.py
windowclass.py
main_gui.py
...
statisticsframe has a class of a frame that shows statistics about stuff.
textframes holds 3 classes of frames holding textareas, one of them inherits Frame, the others inherit the first one.
windowclass basically creates the root of the window and all the general initialization for a tkinter GUI.
main_gui isn't actually the name but it simply combines all the above three and runs the mainloop()
Overall, each file is now 40-60 lines of code.
I am wondering if there are any conventions regarding this. The rule of thumb in most languages is that if you can reuse the functions/ classes elsewhere then you should split, though in Python it is less of a problem since you can import specific classes and functions from modules.
Sorry if it isn't coherent enough, nearly 3AM here and it is simply sitting in the back of my head.
I'm not familiar with tkinter, so my advice would be rather broad.
You can use any split into modules which you feel is better, but
as readability counts try making names coherent and do not repeat yourself: guiclasses - your enire progarm is about GUI, and there obviously classes somewhere, why repeath that in a name? imagine typing all that in in import, make it meaningful to type
flat structure is better than nested, three modules do not have to go to submodule
best split is across layers of abstraction (this is probably hardest and specific to tkinter)
anything in a module shoudl be rather self-sufficient and quite isolated from other parts of the program
modules should make good entitites for unit testing (eg share same fixtures)
can you write an understandable docstring for a module? then it's a good one.
try learning by example, I often seek wisdom for naming and package structure in Barry Warsaw mailman, maybe you can try finding some reputable repo with tkinter to follow (eg IDLE?).
From purely syntatic view I would have named the modules as:
- <package_name>
- baseframe
- textframe
- window
- main

Tracking changes in python source files?

I'm learning python and came into a situation where I need to change the behvaviour of a function. I'm initially a java programmer so in the Java world a change in a function would let Eclipse shows that a lot of source files in Java has errors. That way I can know which files need to get modified. But how would one do such a thing in python considering there are no types?! I'm using TextMate2 for python coding.
Currently I'm doing the brute-force way. Opening every python script file and check where I'm using that function and then modify. But I'm sure this is not the way to deal with large projects!!!
Edit: as an example I define a class called Graph in a python script file. Graph has two objects variables. I created many objects (each with different name!!!) of this class in many script files and then decided that I want to change the name of the object variables! Now I'm going through each file and reading my code again in order to change the names again :(. PLEASE help!
Example: File A has objects x,y,z of class C. File B has objects xx,yy,zz of class C. Class C has two instance variables names that should be changed Foo to Poo and Foo1 to Poo1. Also consider many files like A and B. What would you do to solve this? Are you serisouly going to open each file and search for x,y,z,xx,yy,zz and then change the names individually?!!!
Sounds like you can only code inside an IDE!
Two steps to free yourself from your IDE and become a better programmer.
Write unit tests for your code.
Learn how to use grep
Unit tests will exercise your code and provide reassurance that it is always doing what you wanted it to do. They make refactoring MUCH easier.
grep, what a wonderful tool grep -R 'my_function_name' src will find every reference to your function in files under the directory src.
Also, see this rather wonderful blog post: Unix as an IDE.
Whoa, slow down. The coding process you described is not scalable.
How exactly did you change the behavior of the function? Give specifics, please.
UPDATE: This all sounds like you're trying to implement a class and its methods by cobbling together a motley patchwork of functions and local variables - like I wrongly did when I first learned OO coding in Python. The code smell is that when the type/class of some class internal changes, it should generally not affect the class methods. If you're refactoring all your code every 10 mins, you're doing something seriously wrong. Step back and think about clean decomposition into objects, methods and data members.
(Please give more specifics if you want a more useful answer.)
If you were only changing input types, there might be no need to change the calling code.
(Unless the new fn does something very different to the old one, in which case what was the argument against calling it a different name?)
If you changed the return type, and you can't find a common ancestor type or container (tuple, sequence etc.) to put the return values in, then yes you need to change its caller code. However...
...however if the function should really be a method of a class, declare that class and the method already. The previous paragraph was a code smell that your function really should have been a method, specifically a polymorphic method.
Read about code smells, anti-patterns and When do you know you're dealing with an anti-pattern?. There e.g. you will find a recommendation for the video "Recovery from Addiction - A taste of the Python programming language's concision and elegance from someone who once suffered an addiction to the Java programming language." - Sean Kelly
Also, sounds like you want to use Test-Driven Design and add some unittests.
If you give us the specifics we can critique it better.
You won't get this functionality in a text editor. I use sublime text 3, and I love it, but it doesn't have this functionality. It does however jump to files and functions via its 'Goto Anything' (Ctrl+P) functionality, and its Multiple Selections / Multi Edit is great for small refactoring tasks.
However, when it comes to IDEs, JetBrains pycharm has some of the amazing re-factoring tools that you might be looking for.
The also free Python Tools for Visual Studio (see free install options here which can use the free VS shell) has some excellent Refactoring capabilities and a superb REPL to boot.
I use all three. I spend most of my time in sublime text, I like pycharm for refactoring, and I find PT4VS excellent for very involved prototyping.
Despite python being a dynamically typed language, IDEs can still introspect to a reasonable degree. But, of course, it won't approach the level of Java or C# IDEs. Incidentally, if you are coming over from Java, you may have come across JetBrains IntelliJ, which PyCharm will feel almost identical to.
One's programming style is certainly different between a statically typed language like C# and a dynamic language like python. I find myself doing things in smaller, testable modules. The iteration speed is faster. And in a dynamic language one relies less on IDE tools and more on unit tests that cover the key functionality. If you don't have these you will break things when you refactor.
One answer only specific to your edit:
if your old code was working and does not need to be modified, you could just keep old names as alias of the new ones, resulting in your old code not to be broken. Example:
class MyClass(object):
def __init__(self):
self.t = time.time()
# creating new names
def new_foo(self, arg):
return 'new_foo', arg
def new_bar(self, arg):
return 'new_bar', arg
# now creating functions aliases
foo = new_foo
bar = new_bar
if your code need rework, rewrite your common code, execute everything, and correct any failure. You could also look for any import/instantiation of your class.
One of the tradeoffs between statically and dynamically typed languages is that the latter require less scaffolding in the form of type declarations, but also provide less help with refactoring tools and compile-time error detection. Some Python IDEs do offer a certain level of type inference and help with refactoring, but even the best of them will not be able to match the tools developed for statically typed languages.
Dynamic language programmers typically ensure correctness while refactoring in one or more of the following ways:
Use grep to look for function invocation sites, and fix them. (You would have to do that in languages like Java as well if you wanted to handle reflection.)
Start the application and see what goes wrong.
Write unit tests, if you don't already have them, use a coverage tool to make sure that they cover your whole program, and run the test suite after each change to check that everything still works.

Python class design - Splitting up big classes into multiple ones to group functionality

OK I've got 2 really big classes > 1k lines each that I currently have split up into multiple ones. They then get recombined using multiple inheritance. Now I'm wondering, if there is any cleaner/better more pythonic way of doing this. Completely factoring them out would result in endless amounts of self.otherself.do_something calls, which I don't think is the way it should be done.
To make things clear here's what it currently looks like:
from gui_events import GUIEvents # event handlers
from gui_helpers import GUIHelpers # helper methods that don't directly modify the GUI
# GUI.py
class GUI(gtk.Window, GUIEvents, GUIHelpers):
# general stuff here stuff here
One problem that is result of this is Pylint complaining giving me trillions of "init not called" / "undefined attribute" / "attribute accessed before definition" warnings.
EDIT:
You may want to take a look at the code, to make yourself a picture about what the whole thing actually is.
http://github.com/BonsaiDen/Atarashii/tree/next/atarashii/usr/share/pyshared/atarashii/
Please note, I'm really trying anything to keep this thing as DRY as possible, I'm using pylint to detect code duplication, the only thing it complains about are the imports.
If you want to use multiple inheritance to combine everything into one big class (it might make sense to do this), then you can refactor each of the parent classes so that every method and property is either private (starts with '__') or has a short 2-3 character prefix unique to that class. For example, all the methods and properties in your GUIEvents class could start with ge_, everything in GUIHelpers could start with gh_. By doing this, you'll get achieve some of the clarity of using separate sub-class instances (self.ge.doSomething() vs self.ge_doSomething()) and you'll avoid conflicting member names, which is the main risk when combining such large classes into one.
Start by finding classes that model real world concepts that your application needs to work with. Those are natural candidates for classes.
Try to avoid multiple inheritance as much as possible; it's rarely useful and always somewhat confusing. Instead, look to use functional composition ("HAS-A" relationships) to give rich attributes to your objects made of other objects.
Remember to make each method do one small, specific thing; this necessarily entails breaking up methods that do too many things into smaller pieces.
Refactor cases where you find many such methods are duplicating each other's functionality; this is another way to find natural collections of functionality that deserve to be in a distinct class.
I think this is more of a general OO-design problem than Python problem. Python pretty much gives you all the classic OOP tools, conveniently packaged. You'd have to describe the problem in more detail (e.g. what do the GUIEvents and GUIHelpers classes contain?)
One Python-specific aspect to consider is the following: Python supports multiple programming paradigms, and often the best solution is not OOP. This may be the case here. But again, you'll have to throw in more details to get a meaningful answer.
Your code may be substantially improved by implementing a Model-View-Controller design. Depending on how your GUI and tool are setup, you may also benefit from "widgetizing" portions of your GUI, so that rather than having one giant Model-View-Controller, you have a main Model-View-Controller that manages a bunch of smaller Model-View-Controllers, each for distinct portions of your GUI. This would allow you to break up your tool and GUI into many classes, and you may be able to reuse portions of it, reducing the total amount of code you need to maintain.
While python does support multiple programming paradigms, for GUI tools, the best solution will nearly always be an Object-Oriented design.
One possibility is to assign imported functions to class attributes:
In file a_part_1.py:
def add(self, n):
self.n += n
def __init__(self, n):
self.n = n
And in main class file:
import a_part_1
class A:
__init__ = a_part_1.__init__
add = a_part_1.add
Or if you don't want to update main file when new methods are added:
class A: pass
import a_part_1
for k, v in a_part_1.__dict__.items():
if callable(v):
setattr(A,k,v)

Calling Application Methods from a wx Frame Class

I'm starting out with wxPython and have been working my way through every tutorial and example I can get my hands on. I've run into a slight problem, however, and it has to do with the wx.App versus the wx.Frame and which should contain specific methods. Just about every example I've seen don't go much beyond layouts/sizers and event handling, none really tackle project organization of a wxPython project.
For example, I have a method that gets a list of folders. The way most examples would deal with this would be to stick the method right in the frame class. This method has the potential to be used in several other parts of the application, so it would make more sense to store it at the application class level.
How should I organize and call "universal" methods like these so that I don't clutter up my frame classes.
UPDATE:
To clarify, the "list of folders" was just an example, my actual method does a lot more work. What I'm saying is I have code that isn't Frame-specific. If I had this in the application class, what is the best way to call it from and event method in my frame.
I'm looking for actual project organization techniques, not programming fundamentals.
Your classes that inherit from wxWidgets/wxPython data types should not implement any business logic. wxWidgets is a GUI library, so any subclasses of wxApp or wxFrame should remain focused on GUI, that is on displaying the interface and being responsive to user actions.
The code that does something useful should be separated from wx, as you can decide later to use it in some web or console application and you don't want to create wxApp object in such case. You can also decide later on to move some computations to separate 'worker threads', while your GUI will be the 'main thread' - responsive, and repainted properly during long lasting computations.
Last but not least - the classes that encapsulate your logic might tend to grow during projects lifetime. If they're mixed with your GUI classes they will grow faster, and finally they become so complex that you're almost unable to debug them...
While having them separated leads to clean code when you don't mix bugs in logic with bugs in GUI (refreshing/layout/progress bar etc.). Such approach has another nice feature - ability to split work among GUI-people and logic-people, which can do their work without constant conflicts.
As Mark stated you should make a new class that handles things like this.
The ideal layout of code when using something like wxWidgets is the model view controller where the wxFrame class only has the code needed to display items and all the logic and business rules are handled by other class that interact with the wxFrame. This way you can change logic and business rules with out having to change your interface and change (or swap) your interface with out having to change your logic and business rules.
I probably should have been a lot clearer from the start, but I found what I was looking for:
http://wiki.wxpython.org/ModelViewController/
Burried within the wxpython wiki, I found several simple, concrete examples of MVC projects.
In a proper OOP design, this would be independent or part of a filesystem class - it wouldn't be part of the app or the frame.

Categories