[Share] List Dialog - Simplebrowsing

Below, is just a super simple list dialog using a ui.TableView. Pythonista contains the dialog module which handles this way better. This is just another way to look at it. If you needed a little bit more control for example. Anyway, I was just playing around and thought i would post it. I did get a little confused accessing variables outside the delegate closure. I followed a pattern that I found on stackflow for python 2. I could not assign to the outter scoped var my_sel the way that I thought I could based on the docs for py3 using nonlocal.
This is a language construct, so cant believe its a bug. I am just doing something wrong.

import ui
'''
ui.ListDataSource = LDS
Very crude example of a list dialog.
Just to show how easy it can be if you have very simple needs.
last_name is intentionally not displayed. LDS only knows about title,
image and accessory_type.
But the fact the dict contains other keys is not an issue.
'''
def show_list_dialog(items=None, *args, **kwargs):
'''
depending on your needs this could be your list dialog, you
use over and over, although you would not because dialogs
module has one already.
'''
items = items or [] # hmmmm thanks @ccc
tbl = ui.TableView(**kwargs)
tbl.data_source = ui.ListDataSource(items)
# i used this because I could not get nonlocal working
# as I thought it should work, i wanted to just use my_sel = None
my_sel = {'value': None}
class MyTableViewDelegate (object):
# nonlocal my_sel (does not work as I understand it should)
def tableview_did_select(self, tableview, section, row):
my_sel['value'] = tableview.data_source.items[row]
tableview.close()
tbl.delegate = MyTableViewDelegate()
tbl.present(style='sheet')
tbl.wait_modal() # This method is what makes this a dialog(modal)
return my_sel['value']
if __name__ == '__main__':
f = (0, 0, 400, 300)
items = [{'title': 'Ian', 'last_name': "Jones"},
{'title': 'Christian', 'last_name': "Smith"}]
# uncomment the line below, to see the difference
# items = ['Ian', 'John', 'Paul', 'Ringo']
result = show_list_dialog(items, frame=f, name='Select a Name')
print(result)

Also you can avoid creating MyTableViewDelegate by using data source as delegate and using data source's action. If you'd like to display something else than just title value, you can create your data source in this way and pass whatever you want as an item.

@zrzka , nice. That's why I dont mind doing these simple examples. You can learn a lot from peoples input. I am still not sure why my nonlocal approached did work and yours does. But its the first time I have ever even used it. In my example, I was trying to simplify to a function instead of a class, because I think when guys are learning the ui module/python beginners, including me it can appear very daunting. I think the classes eventually simplify a lot of it. Anyway, its still all fun. And even though I have gotten away with using closures before, I didn't really understand the scoping. In my example I was trying to understand it.

@Phuket2 you did mention that you were trying to understand scopes. Here're some explanations of how global and nonlocal works. It's simplified and it's still recommended to read Python documentation to fully understand it. But this should help a bit.

Ouch, what's going on one can say. I didn't use global here, but it was modified.

What is variable? It's called name in Python and every name refers to an object. This is called binding. You can read more here if you're interested (chapter 4.2.).

Basically everything is an object in Python. Really? What about primitive types for example? Python has no primitive types you know from Java or Objective C. Everything is an object in Python, even bool, int, ...

What plays big role here is mutability vs immutability and if you're mutating in place or assigning new object. Some types are immutable (bool, int, float, tuple, str, frozenset) and some are mutable (list, set, dict). Immutable objects can't be modified after you create them, mutable can.

x is of type int. This type is immutable. It looks like mutable type, but it isn't. Whenever you do x += 1, new object is created and x is rebinded to this new object. If type of your variable is immutable and you want to modify it, you have to use global.

y is of type list. This type is mutable. Whenever you do y.append('b'), it's still the same object. .append mutates it in place. Also y[:] = ['a', 'b'] mutates the list in place. It replaces all elements in the list, but it's done in place, no new object is created. So, you don't need global here as well.

But don't forget that simple assignment like y = ['a', 'b', 'c'] rebinds y variable to the new object (you're not mutating it in place) and you must use global in this case.

Let's pretend that you can't access class instance attributes prefixed with _ (actually you can, but let's pretend you can't). Following example shows immutable type Contact. If you want to modify name, you have to create new object (there's no setter for name property).

nonlocal

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

@zrzka, wow. Thanks for the fantastic explanation. I haven't gone though it in detail yet, but I will. I was a pascal/c/vb programmer many many years ok. Even though its so long ago, I often do things how I remember I think they should be done. Maybe global is ok to use in Python for example, but i would hate myself if I found I had too use it for some reason. The nonlocal seemed to make sense to me when I wanted to start to use closures and be able to interact with the outter scopes vars in a somewhat correct manner (but its possibly also considered spaghetti code, not sure) . But I have been cheating :) eg, i would add a runtime attr to an object to read and write because on not understanding these scope rules.
I find it a little funny how they say Python is one of the easiest languages to learn. I am sure its correct in some contexts. But the richness of the language makes it somewhat challenging in my mind. C was hard, but it was fairly rigid. In someways that was nice once you got the hang of it. Anyway, I am waffling on.
Really thanks again. I will go though your sample code carefully. Hopefully other newbies here will also.

Maybe global is ok to use in Python for example, but i would hate myself if I found I had too use it for some reason.

Why? Sometimes it's perfectly ok to use it. There're other ways how to achieve your goal sometimes. Depends. Globals are here and I'm not fan of globals are evil and also not fan of globals are perfect, let's use them everywhere. Just be pragmatic and use the simplest way.

The nonlocal seemed to make sense to me when I wanted to start to use closures and be able to interact with the outter scopes vars in a somewhat correct manner (but its possibly also considered spaghetti code, not sure) . But I have been cheating :) eg, i would add a runtime attr to an object to read and write because on not understanding these scope rules.

In the end the only thing which matters is readability / maintainability. If it's clear what the code is doing, it's fine. Everyone has it's own style, patterns, ... Just don't be too clever or you (or others) will not understand your code after week, month, ...

I find it a little funny how they say Python is one of the easiest languages to learn. I am sure its correct in some contexts. But the richness of the language makes it somewhat challenging in my mind.

Yes, it's easy. The problem here is discipline. Python allows you to do everything and you have to maintain discipline to be a good citizen. And sometimes people don't maintain it, stuff brakes, ... Sometimes they have no clue why, because they didn't read documentation, ...

C was hard, but it was fairly rigid.

I don't consider C as hard, but I think it's harder compared to Python. Not because it's really hard itself, but because code can contain lot of pointer arithmetics, manual memory management, ... and it's unclear what it does when you look at it for the first time. Anyway it was one of my first languages (when I skip BASIC, ...), I like it and I still use it. Remember good old times with Watcom C, protected mode, ... fun without documentation & internet :)