On Tue, 25 Jan 2000, Skip Montanaro wrote: > > Guido> I think it depends on to what extent this is a common, useful > Guido> idiom. Do you have evidence of that? Examples? > > Well, the first place I ran into it was in DocumentTemplates a few years > ago. They used an idiom heavily which may have now been replaced by > acquisition where you'd effectively push and pop value dicts onto a stack as > you entered and exited nested blocks of DTML code. Their solution was a > special dict-like object. That's really interesting. I wrote a bunch of Python wrappers for a UI toolkit a little while ago, and there were two main pieces of machinery i built to make the toolkit pleasant to use: 1. a reasonably nice C++ extension class kit (this is where i tried overloading operator new for the first time, so it would allocate memory that could be freed by PyMem_DEL -- i don't know if CXX uses the same approach) 2. a second layer of Python wrapper classes for the extension classes that implements extra methods in Python, and maintains a hierarchy of default keyword argument values along the inheritance hierarchy of widgets The second of these things involved implementing exactly the kind of dictionary stack that you mentioned. The programming idiom for building widgets goes something like: defaultstack = {} # maps class object to list of defaults dictionaries class Label(Component): defaults = _dict(text="Label", align=LEFT) class Button(Label): defaults = _dict(text="Button", align=CENTER, shadow=2) ... w = Window(...) Button.push(fg="white", bg="red", font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*") a = Button(w, text="one") b = Button(w, text="two") c = Button(w, text="three") Button.pop() This way you can install some options for a while and make a bunch of widgets with your defaults, then pop the options and go back to the previous state. The layers of dictionaries that get composed in every widget's __init__ function are (in order of priority): 1. any non-None keyword arguments to __init__ 2. any non-None values in class.defaults 3. any non-None values in class.__bases__[0].defaults 4. any non-None values in class.__bases__[0].__bases__[0].defaults etc. When a new set of defaults is push()ed, the class's current defaults are saved on the defaultstack for the class, and restored when pop() gets called. I don't *know* if this is really the best way to do things, but it has seemed to work out pretty well in practice. It makes it more convenient to deal with all the options you have to throw around especially when doing UI stuff. Anyway, i noticed the same sort of thing today while wondering about using keyword arguments for HTML tag attributes. (Perhaps HTMLgen does this sort of thing already -- sorry i haven't looked at it.) Anyway, the following sort of helper might be useful in general: class Default: def __init__(self, cl, **defaults): self.cl = cl self.defaults = defaults def __call__(self, *args, **kw): for key, value in self.defaults: if not kw.has_key(key): kw[key] = value return apply(self.cl, args, kw) Then you could do the same thing as above with: MyButton = Default(Button, fg="white", bg="red", font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*") a = MyButton(w, text="one") b = MyButton(w, text="two") c = MyButton(w, text="three") This is probably a cleaner way to do things. I haven't tried it, but it might be a nice thing to have in Tkinter. -- ?!ng
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4