So I've used python as a functional language for a while but I'm trying to do thing "right" and use classes now... and falling down. I'm trying to write a classmethod that can instantiate multiple members of the class (use case is load rows from SQLAlchemy.) I'd like to just be able to call the classmethod and have it return a status code (success/failure) rather than returning a list of objects. Then to access the objects I'll iterate through the class. Here's my code so far (which fails to iterate when I use the classmethod, works fine when I use the normal constructor.) Am I way off-base/crazy here? What's the "pythonic" way to do this? Any help is appreciated and thank you.
class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self))
#classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst
class Credentials(KeepRefs):
def __init__(self,name, username, password):
super(Credentials, self).__init__()
self.name=name
self.username=username
self.password=password
#classmethod
def loadcreds(cls):
Credentials('customer1','bob','password')
return True
success = Credentials.loadcreds()
for i in Credentials.get_instances():
print (i.name)
In your own words - yes, you are off-base and crazy :)
Status-Codes are a thing of C, not languages with proper exception semantics as Python. Modifying global state is a sure recipe for disaster. So - don't do it. Return a list of objects. Throw an exception if something disastrous happens, and just return an empty list if there happen to be no objects. This allows the client code to just do
for item in Thingies.load_thingies():
... # this won't do anything if load_thingies gave us an empty list
without having to painstakingly check something before using it.
Functional languages have certain advantages, and you are going too far the other way in your exploration of the procedural style. Global variables and class variable have their place, but what will happen if you need to fire off two SQAlchemy queries and consume the results in parallels? The second query will stomp over the class attributes that the first one still needs, is what. Using an object attribute (instance attribute) solves the problem, since each result contains its own handle.
If your concern is to avoid pre-fetching the array of results, you are in luck because Python offers the perfect solution: Generators, which are basically lazy functions. They are so nicely integrated in Python, I bet you didn't know you've been using them with every for-loop you write.
First question on SO! Bear with me, there is a bit of background context needed.
I started using classes to make a data storage container similar to struct in matlab. When going open source with Python, I have not completely replaced this and it is very useful when combining more than just numeric array data, or just makes more sense to reference things with names instead of indicies.
I realized using classes was not the best thing to do for several layers deep (right? mostly just confusing and maybe slow), and I need a generic tree data type. I am working on a project to automate Excel, and data must be stored based on what is in the cell, later operated on, and potentially rewritten back to some areas of the spreadsheet. And who wants to write in VBA when we can use xlwings and openpyxl to leverage other stuff we have written in an adaptable, OS portable language like Python?!
Building upon this post:
Looking for a good Python Tree data structure
I liked the expandability of this:
import collections
def Tree():
return collections.defaultdict(Tree)
I can make arbitrary layers of any type. I also wanted to also include some functions to manage it like I had in my class storage containers as demonstrated in the UserData class at the bottom of this post. There is an example of it being used in a class on that pagewhich sort of works:
class Tree(defaultdict):
def __call__(self):
return Tree(self)
def __init__(self, parent):
self.parent = parent
self.default_factory = self
So I experimented, worked out kinks, and made this class:
import collections
class TreeClass(collections.defaultdict):
def __call__(self):
return TreeClass(self)
def Tree(self):
return collections.defaultdict(self.Tree)
def __init__(self, parent):
self.parent = parent
self.default_factory = self
#self.x = 'xvar'
#self._locations_idx=[]
self['someInitKey'] = 'value'
The reason I want the class and the functionality of the data structure operating on itself is to do something like this:
import openpyxl.utils as opx
class UserData():
'''For more info on decorators:
https://stackoverflow.com/questions/27571546/dynamically-update-attributes-of-an-object-that-depend-on-the-state-of-other-att
https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work
'''
def __init__(self):
self.locations=[]
self._locations_idx=[]
#property # Auto update locations_idx when locations changes
def locations_idx(self):#, locations=self.locations):
self._locations_idx = self.locations # set list to same len
for i in range(len(self.locations)):
current_loc = self.locations[i]
# write indexed location over copy of list of same len
# TODO check make sure this is zero indexed
self._locations_idx[i] = (opx.column_index_from_string(current_loc[0]), int(current_loc[1]))
return self._locations_idx
where opx.column_index_from_string is a function from openpyxl to return the corresponding 0-indexed index from a letter, and it is combined into a tuple to turn a list of 'A1', 'B2' into a list of (0,0), (1,1) etc
This way, though the class is initialized with an empty locations list, when the list is populated with 'C4', 'B22' etc, the myUserData.locations_idx contains an updated list of these indices which are very useful for the rest of the program when you don't want to reference contents by 'excel location'.
Now for my actual question:
Say I use this to make a default dict of schema defaultdict[carMake][carModel][carColor][locationInSpreadsheet] like following:
myUserData['toyota']['corolla']['grey']['location']='B2'
myUserData['chevy']['Volt']['blue']['location']='B6'
and upon adding a 'location' key/value, I would like to dynamically create corresponding:
myUserData['chevy']['Volt']['blue']['location_idx']
which returns (1,5).
Only thing is I am new to default_dict, rarely need to OOP Python, not sure what to even google (referencing many layers into a tree data structure made from default dict python ?). Can someone help or give me some pointers? I hate to drag on other people and have made it a long way in Python without needing to ask a question on here, but I've hit my limit when I don't even know what to look for. I hope you can tell what I'm trying to do from the examples, and I think I'm approaching this problem the right way. Any post formatting/etiquette, tag suggestions, are welcome too. If something is unclear, please let me know, but I have tried to make the examples general enough and easy to understand that someone who works with Python classes and default dicts should be able to understand. I think. Thanks for any help!
Am having much trouble splitting PyQt code:
main.py
(PyQt modules)
from titles import *
appl = QApplication(sys.argv)
from main import Ui_MainWindow
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
QMainWindow.__init__(self)
self.u = Ui_MainWindow()
self.u.setupUi(self)
Titles(self)
titles.py
import sys
(PyQt modules)
(dbconnections)
class Titles():
def __init__(self, a): #<-- APP IS PASSED AS ARGUMENT AND NOW CALLED 'A'
a.u.table.setModel(titles)
a.u.lineEdit.setText("Titles Init")
a.u.add.clicked.connect(titles.insertRow)
class TitlesTableModel(QSqlTableModel):
def __init__(self):
QSqlTableModel.__init__(self)
self.setTable("titles")
self.setEditStrategy(self.OnFieldChange)
self.select()
def insertRow(self):
return self.insertRecord(-1, self.record())
a.u.lineEdit.setText("Insert Title")
titles = Titles()
Running main.py loads all data. QPushButton inserts a row, but doesn't set lineEdit to "Insert Title", because "a" isn't defined globally. Mostly tried creating a function in titles.py, triggered when main.py loads, looking like:
a = 0 #<-- THIS WAS A LAST STRAW AS WARNED BY RESEARCHING OTHERS, BUT AM LOST
def start(app):
global a
a = app
Titles(a); TitlesTableModel(a) #<-- EVEN THOUGH TITLES.PY IS IMPORTED, IT DIDN'T INCLUDE THE APP REFERENCE, SO AM TRYING TO 'REFRESH' THE TITLESTABLEMODEL
...with Titles & TitlesTableModel requiring an extra argument (self, a)
This loads data & functions, but again, insertRow doesn't update lineEdit.
Other attempt
change Songs class to
class Songs():
def __init__(self, a):
titles = Titles(a)
...(rest the same)
...and removing titles=Titles() from below the model definition. This again, shows data, but doesn't update lineEdit when pressing 'Add'.
Ultimately, it feels titles.py needs to have 'from main import *', but the main applications instance is defined after titles.py is called, and importing main.Main creates a recursion. Have tried inheriting multiple times via 'from main import Main', & writing 'class Songs(Main)' (so Songs can use the UI without passing a reference), but again, recursion occurs. Nine hours today plus three weeks prior looking at others, so am really stumped. Others somewhat recommended using a config file of even 'builtin', but that looks very bad.
Regards
In PyQt, classes generally use Signals to communicate between one another, especially when one class inherits from QWidget and the other does not inherit from that, as you've demonstrated by connecting signals (albeit wrongly, or at least you're missing bits and pieces of your code here on SO).
However, your insertRow() -> lineEdit method as it stands will never be called because it follows a return statement, meaning that the lineEdit part will never be hit. But I would be surprised if this fixed the problem.
Also, I would consider redesigning (refactoring) your code from the grounds up. Is there really a reason you have a different Titles() class?
While this is shameless self-promotion, I think you might benefit from my course on YouTube that deals with building Python applications using PySide (which is nearly identical to PyQt) - I discuss cross-thread (cross-class) communication a fair bit - link is http://youtube.com/Deusdies2
Your code has several issues, but the main problem is the snippet:
def insertRow(self):
return self.insertRecord(-1, self.record())
a.u.lineEdit.setText("Insert Title")
as you can see you're returning from the function before the line a.u.lineEdit.setText("Insert Title") get excecuted. Hence, this function willl never change the text of your QLineEdit.
Change your code b
def insertRow(self):
a.u.lineEdit.setText("Insert Title") # First change text.
return self.insertRecord(-1, self.record()) # Then insert record and return.
On the other hand: If you are working with global variables (a bad practice, I have to say) why are you passing it as arguments? Try to not use global variables at least is absolutly necesary.
I'm new to programming, and have recently learned python and the basics of object oriented programming. I'm aware that having lots of global variables is generally a bad idea, and that I can put them all into a class instead. Is this the right way to do it?
class GameState(object):
def __init__(self):
self.variable1 = 1
self.variable2 = 2
self.list = [3, 4, 5]
g_state = GameState()
And, if I wish to access the variables within g_state, what is the best way to go about doing it?
Pass g_state into the functions/classes that need access?
Implement getters and call those?
Use g_state.variable1 directly?
Or is there a better way?
EDIT: To be more specific, I'm trying to write a game in python using pygame, and was thinking of putting my gamestate variables into a class so as to not have a bunch of global variables lying around. I'm unsure of how to access those variables with good design so I don't run into trouble later.
You are right that too many global variables is not a good idea. Polluted global namespace may lead to errors.
However, don't put them into class for the sake of it. If you have really that many variables maybe you should consider splitting your program into multiple modules.
Also please understand that you can't really crate global variables in Python like you can in JavaScript. Your variables are always scoped under the module.
Let me illustrate with an example. Module a.py:
A = 42
Module b.py:
import a
print(A)
What do you get? NameError. Why? because variable A is not global, it is under module a. You need to use a.A to reference it.
There is no need to stuff variables under class. They are under modules, which acts as a namespace, and there is nothing wrong with it.
There are two ways to access the variables: one global object or passing an instance to a function. The first one is a bad idea too in general. The second one is better. But do not create a single object with all variables! (see the first comment).
There are more things to consider if you pass around an object. A good idea is implementing things as a member-function if suitable.
class VariableBox(object):
def __init__(self):
self.variable1 = 1
self.variable2 = 2
self.list = [3, 4, 5]
def do_something(self):
self.variable1 = self.variable2 + 42
return self.variable1
Creating a class simply for storing variables is not necessary. A class would only be needed if you really do need multiple instances of that class, each with unique values.
But for a single global state, a dictionary object can suffice for this purpose. You can store it in a module specifically intended for config and state if you want:
conf.py
GAME_STATE = {
'level': 0,
'score': 0,
'misc': [1,2,3],
}
main.py
import conf
conf.GAME_STATE['score'] = 100
So your other modules can just import the conf.py module and access the state dict. You can store whatever types you need in this object. It also gives you a convenient location to add functionality for serializing these values out to disk if you want, and reading them back at future runs of the program, and to keep them alongside configuration options.
NO!!! Building a VariableBox will help you NOT!
Simply use the var you want, wherever it may applies. If you have too many global vars, it's rather a problem with what should be considered global, and what should pertain to specific structures. Or even a difficulty in naming the vars, or creating arrays, instead of var1, var2, var3, ....
Classes are designed for building of objects, i. e., for creating things that differ for specificities, but have the same basis. A valuable class is something that somewhat defines an entity, and the main behaviors of this entity.
EDIT:
Python does not provide visibility constraints, so you won't be able to protect data by simply stuffing it into a class; the entries can be accessed from any place an instance of the class is.
Creating getters or simply maintaining an instance of a class is just a matter of deciding which one to work with. For the sake of maintaining things clear, it may be better to make a controller to your game, that will make this interface between game assets and gameplay.
For example, during execution, you could have:
class Controller:
def __init__():
self.turn = 0
self. ...
def begin():
self.turn += 1
self.opening_scene()
class Gameplay:
def __init__(self, num_players, turn, ...):
self.turn = turn # if it happens you want to use this value in the game
self.num_player = num_players
# Main loop
controller = Controller()
controller.num_players = int(raw_input("Number of players: "))
gameplay = Gameplay(controller.num_players, controller.turn)
while True:
if gameplay.action == ...:
elif ...:
...
elif *next turn*:
controller.next_turn() # to set things up to next turn
else ...:
...
Inside Controller you may aggregate correlated info, so you won't have an endless list of parameters in the upcoming functions.
Anyway, I'm not capable of telling you which is the best to use; there are lots of people that study these modularity issues, and I'm not one of them, so this is just my point of view on what could work out nice on your app.
I have been playing with the Ruby library "shoes". Basically you can write a GUI application in the following way:
Shoes.app do
t = para "Not clicked!"
button "The Label" do
alert "You clicked the button!" # when clicked, make an alert
t.replace "Clicked!" # ..and replace the label's text
end
end
This made me think - how would I design a similarly nice-to-use GUI framework in Python? One that doesn't have the usual tyings of basically being wrappers to a C* library (In the case of GTK, Tk, wx, QT etc etc)
Shoes takes things from web devlopment (like #f0c2f0 style colour notation, CSS layout techniques, like :margin => 10), and from ruby (extensively using blocks in sensible ways)
Python's lack of "rubyish blocks" makes a (metaphorically)-direct port impossible:
def Shoeless(Shoes.app):
self.t = para("Not clicked!")
def on_click_func(self):
alert("You clicked the button!")
self.t.replace("clicked!")
b = button("The label", click=self.on_click_func)
No where near as clean, and wouldn't be nearly as flexible, and I'm not even sure if it would be implementable.
Using decorators seems like an interesting way to map blocks of code to a specific action:
class BaseControl:
def __init__(self):
self.func = None
def clicked(self, func):
self.func = func
def __call__(self):
if self.func is not None:
self.func()
class Button(BaseControl):
pass
class Label(BaseControl):
pass
# The actual applications code (that the end-user would write)
class MyApp:
ok = Button()
la = Label()
#ok.clicked
def clickeryHappened():
print "OK Clicked!"
if __name__ == '__main__':
a = MyApp()
a.ok() # trigger the clicked action
Basically the decorator function stores the function, then when the action occurred (say, a click) the appropriate function would be executed.
The scope of various stuff (say, the la label in the above example) could be rather complicated, but it seems doable in a fairly neat manner..
You could actually pull this off, but it would require using metaclasses, which are deep magic (there be dragons). If you want an intro to metaclasses, there's a series of articles from IBM which manage to introduce the ideas without melting your brain.
The source code from an ORM like SQLObject might help, too, since it uses this same kind of declarative syntax.
I was never satisfied with David Mertz's articles at IBM on metaclsses so I recently wrote my own metaclass article. Enjoy.
This is extremely contrived and not pythonic at all, but here's my attempt at a semi-literal translation using the new "with" statement.
with Shoes():
t = Para("Not clicked!")
with Button("The Label"):
Alert("You clicked the button!")
t.replace("Clicked!")
The hardest part is dealing with the fact that python will not give us anonymous functions with more than one statement in them. To get around that, we could create a list of commands and run through those...
Anyway, here's the backend code I ran this with:
context = None
class Nestable(object):
def __init__(self,caption=None):
self.caption = caption
self.things = []
global context
if context:
context.add(self)
def __enter__(self):
global context
self.parent = context
context = self
def __exit__(self, type, value, traceback):
global context
context = self.parent
def add(self,thing):
self.things.append(thing)
print "Adding a %s to %s" % (thing,self)
def __str__(self):
return "%s(%s)" % (self.__class__.__name__, self.caption)
class Shoes(Nestable):
pass
class Button(Nestable):
pass
class Alert(Nestable):
pass
class Para(Nestable):
def replace(self,caption):
Command(self,"replace",caption)
class Command(Nestable):
def __init__(self, target, command, caption):
self.command = command
self.target = target
Nestable.__init__(self,caption)
def __str__(self):
return "Command(%s text of %s with \"%s\")" % (self.command, self.target, self.caption)
def execute(self):
self.target.caption = self.caption
## All you need is this class:
class MainWindow(Window):
my_button = Button('Click Me')
my_paragraph = Text('This is the text you wish to place')
my_alert = AlertBox('What what what!!!')
#my_button.clicked
def my_button_clicked(self, button, event):
self.my_paragraph.text.append('And now you clicked on it, the button that is.')
#my_paragraph.text.changed
def my_paragraph_text_changed(self, text, event):
self.button.text = 'No more clicks!'
#my_button.text.changed
def my_button_text_changed(self, text, event):
self.my_alert.show()
## The Style class is automatically gnerated by the framework
## but you can override it by defining it in the class:
##
## class MainWindow(Window):
## class Style:
## my_blah = {'style-info': 'value'}
##
## or like you see below:
class Style:
my_button = {
'background-color': '#ccc',
'font-size': '14px'}
my_paragraph = {
'background-color': '#fff',
'color': '#000',
'font-size': '14px',
'border': '1px solid black',
'border-radius': '3px'}
MainWindow.Style = Style
## The layout class is automatically generated
## by the framework but you can override it by defining it
## in the class, same as the Style class above, or by
## defining it like this:
class MainLayout(Layout):
def __init__(self, style):
# It takes the custom or automatically generated style class upon instantiation
style.window.pack(HBox().pack(style.my_paragraph, style.my_button))
MainWindow.Layout = MainLayout
if __name__ == '__main__':
run(App(main=MainWindow))
It would be relatively easy to do in python with a bit of that metaclass python magic know how. Which I have. And a knowledge of PyGTK. Which I also have. Gets ideas?
With some Metaclass magic to keep the ordering I have the following working. I'm not sure how pythonic it is but it is good fun for creating simple things.
class w(Wndw):
title='Hello World'
class txt(Txt): # either a new class
text='Insert name here'
lbl=Lbl(text='Hello') # or an instance
class greet(Bbt):
text='Greet'
def click(self): #on_click method
self.frame.lbl.text='Hello %s.'%self.frame.txt.text
app=w()
The only attempt to do this that I know of is Hans Nowak's Wax (which is unfortunately dead).
The closest you can get to rubyish blocks is the with statement from pep343:
http://www.python.org/dev/peps/pep-0343/
If you use PyGTK with glade and this glade wrapper, then PyGTK actually becomes somewhat pythonic. A little at least.
Basically, you create the GUI layout in Glade. You also specify event callbacks in glade. Then you write a class for your window like this:
class MyWindow(GladeWrapper):
GladeWrapper.__init__(self, "my_glade_file.xml", "mainWindow")
self.GtkWindow.show()
def button_click_event (self, *args):
self.button1.set_label("CLICKED")
Here, I'm assuming that I have a GTK Button somewhere called button1 and that I specified button_click_event as the clicked callback. The glade wrapper takes a lot of effort out of event mapping.
If I were to design a Pythonic GUI library, I would support something similar, to aid rapid development. The only difference is that I would ensure that the widgets have a more pythonic interface too. The current PyGTK classes seem very C to me, except that I use foo.bar(...) instead of bar(foo, ...) though I'm not sure exactly what I'd do differently. Probably allow for a Django models style declarative means of specifying widgets and events in code and allowing you to access data though iterators (where it makes sense, eg widget lists perhaps), though I haven't really thought about it.
Maybe not as slick as the Ruby version, but how about something like this:
from Boots import App, Para, Button, alert
def Shoeless(App):
t = Para(text = 'Not Clicked')
b = Button(label = 'The label')
def on_b_clicked(self):
alert('You clicked the button!')
self.t.text = 'Clicked!'
Like Justin said, to implement this you would need to use a custom metaclass on class App, and a bunch of properties on Para and Button. This actually wouldn't be too hard.
The problem you run into next is: how do you keep track of the order that things appear in the class definition? In Python 2.x, there is no way to know if t should be above b or the other way around, since you receive the contents of the class definition as a python dict.
However, in Python 3.0 metaclasses are being changed in a couple of (minor) ways. One of them is the __prepare__ method, which allows you to supply your own custom dictionary-like object to be used instead -- this means you'll be able to track the order in which items are defined, and position them accordingly in the window.
This could be an oversimplification, i don't think it would be a good idea to try to make a general purpose ui library this way. On the other hand you could use this approach (metaclasses and friends) to simplify the definition of certain classes of user interfaces for an existing ui library and depending of the application that could actually save you a significant amount of time and code lines.
I have this same problem. I wan to to create a wrapper around any GUI toolkit for Python that is easy to use, and inspired by Shoes, but needs to be a OOP approach (against ruby blocks).
More information in: http://wiki.alcidesfonseca.com/blog/python-universal-gui-revisited
Anyone's welcome to join the project.
If you really want to code UI, you could try to get something similar to django's ORM; sth like this to get a simple help browser:
class MyWindow(Window):
class VBox:
entry = Entry()
bigtext = TextView()
def on_entry_accepted(text):
bigtext.value = eval(text).__doc__
The idea would be to interpret some containers (like windows) as simple classes, some containers (like tables, v/hboxes) recognized by object names, and simple widgets as objects.
I dont think one would have to name all containers inside a window, so some shortcuts (like old-style classes being recognized as widgets by names) would be desirable.
About the order of elements: in MyWindow above you don't have to track this (window is conceptually a one-slot container). In other containers you can try to keep track of the order assuming that each widget constructor have access to some global widget list. This is how it is done in django (AFAIK).
Few hacks here, few tweaks there... There are still few things to think of, but I believe it is possible... and usable, as long as you don't build complicated UIs.
However I am pretty happy with PyGTK+Glade. UI is just kind of data for me and it should be treated as data. There's just too much parameters to tweak (like spacing in different places) and it is better to manage that using a GUI tool. Therefore I build my UI in glade, save as xml and parse using gtk.glade.XML().
Personally, I would try to implement JQuery like API in a GUI framework.
class MyWindow(Window):
contents = (
para('Hello World!'),
button('Click Me', id='ok'),
para('Epilog'),
)
def __init__(self):
self['#ok'].click(self.message)
self['para'].hover(self.blend_in, self.blend_out)
def message(self):
print 'You clicked!'
def blend_in(self, object):
object.background = '#333333'
def blend_out(self, object):
object.background = 'WindowBackground'
Here's an approach that goes about GUI definitions a bit differently using class-based meta-programming rather than inheritance.
This is largley Django/SQLAlchemy inspired in that it is heavily based on meta-programming and separates your GUI code from your "code code". I also think it should make heavy use of layout managers like Java does because when you're dropping code, no one wants to constantly tweak pixel alignment. I also think it would be cool if we could have CSS-like properties.
Here is a rough brainstormed example that will show a column with a label on top, then a text box, then a button to click on the bottom which shows a message.
from happygui.controls import *
MAIN_WINDOW = Window(width="500px", height="350px",
my_layout=ColumnLayout(padding="10px",
my_label=Label(text="What's your name kiddo?", bold=True, align="center"),
my_edit=EditBox(placeholder=""),
my_btn=Button(text="CLICK ME!", on_click=Handler('module.file.btn_clicked')),
),
)
MAIN_WINDOW.show()
def btn_clicked(sender): # could easily be in a handlers.py file
name = MAIN_WINDOW.my_layout.my_edit.text
# same thing: name = sender.parent.my_edit.text
# best practice, immune to structure change: MAIN_WINDOW.find('my_edit').text
MessageBox("Your name is '%s'" % ()).show(modal=True)
One cool thing to notice is the way you can reference the input of my_edit by saying MAIN_WINDOW.my_layout.my_edit.text. In the declaration for the window, I think it's important to be able to arbitrarily name controls in the function kwargs.
Here is the same app only using absolute positioning (the controls will appear in different places because we're not using a fancy layout manager):
from happygui.controls import *
MAIN_WINDOW = Window(width="500px", height="350px",
my_label=Label(text="What's your name kiddo?", bold=True, align="center", x="10px", y="10px", width="300px", height="100px"),
my_edit=EditBox(placeholder="", x="10px", y="110px", width="300px", height="100px"),
my_btn=Button(text="CLICK ME!", on_click=Handler('module.file.btn_clicked'), x="10px", y="210px", width="300px", height="100px"),
)
MAIN_WINDOW.show()
def btn_clicked(sender): # could easily be in a handlers.py file
name = MAIN_WINDOW.my_edit.text
# same thing: name = sender.parent.my_edit.text
# best practice, immune to structure change: MAIN_WINDOW.find('my_edit').text
MessageBox("Your name is '%s'" % ()).show(modal=True)
I'm not entirely sure yet if this is a super great approach, but I definitely think it's on the right path. I don't have time to explore this idea more, but if someone took this up as a project, I would love them.
Declarative is not necessarily more (or less) pythonic than functional IMHO. I think a layered approach would be the best (from buttom up):
A native layer that accepts and returns python data types.
A functional dynamic layer.
One or more declarative/object-oriented layers.
Similar to Elixir + SQLAlchemy.