To the good people on comp.lang.python: I have the following Tkinter class (python 2.7.3):
from Tkinter import * class ScrolledCanvas(Frame): def __init__(self, master, width, height, bg, cursor): Frame.__init__(self, master) self.__nonzero__ = lambda: True canv = self.canvas = Canvas(self, bg=bg, relief=SUNKEN) # self.__getattr__ = lambda x, name: getattr(self.canvas, name) canv.config(width=width, height=height) # display area size canv.config(scrollregion=(0, 0, width, height)) # canvas size corners canv.config(highlightthickness=0) # no pixels to border ybar = Scrollbar(self) ybar.config(command=canv.yview) # xlink sbar and canv canv.config(yscrollcommand=ybar.set) # move one moves other xbar = Scrollbar(self) xbar.config(command=canv.xview) # xlink sbar and canv canv.config(xscrollcommand=xbar.set) # move one moves other canv.grid(row = 0, column = 0, sticky = 'news') ybar.grid(row = 0, column = 1, sticky = 'ns') xbar.grid(row = 1, column = 0, sticky = 'ew') self.rowconfigure(0, weight = 1) self.columnconfigure(0, weight = 1) self.create_text(20, 20, text = 'Did it!', fill = 'red') def __getattr__(self, name): return getattr(self.canvas, name) root = Tk() app = ScrolledCanvas(root, 400, 300, 'white', 'hand2') app.pack() root.mainloop() I just added the __getattr__ method, and the program crashed in the Canvas constructor. There is apparently a call to self.__nonzero__ somewhere in Tkinter.py, and since the constructor hasn't exited yet, sel.fcanvas isn't defined yet, so __getattr__ recurses indefinitely. I fixed this as you see, by defining self.__nonzero__ before the call to the constructor. Now, I have two questions: 1. I originally defined self.__nonzero__ = lambda x: True, on the assumption that when self.__nonzero__ was called, the interpreter would pass self as an argument. Wrong. No arguments were passed. Why is this? 2. I find this solution rather unsatisfactory, since there's a rather obscure line of code here. I tried eliminating the def of __gertattr__ and the definition of self.__nonzero__ and adding this line after the constructor: self.__getattr__= lambda name: getattr(self.canvas, name) This get through the constructor all right, but crashes with the message that a ScrolledCanvas object has no create_text attribute. (I've tried passing two arguments to the lambda, but it makes no difference.) I don't understand what's going on at all. Can't I dynamically define __getattr__? How should I go about it? By the way, another thing that didn't work was calling the method delegate instead of __getattr__. Then after the constructor call, I wrote self.__getattr__ = self.delegate. This crashed as before on self.create_text. I just tried a little experiment with __add__ and had no success, so I guess my problem is with overloaded operators in general. I'd really appreciate an explanation, or a pointer to relevant documentation. -- http://mail.python.org/mailman/listinfo/python-list