r0g wrote: > On 10/11/10 09:52, Peter Otten wrote: >> class PlainAJAXRequestHandler(BaseHTTPRequestHandler): >> def __init__(self, api_call, paths, *args, **kw): >> BaseHTTPRequestHandler.__init__(self, *args, **kw) >> self.api_call = api_call >> self.paths = paths > > > Hmm, the plot thickens! I always thought you had to call the parent > constructor first (as above) when extending a constructor (not that I've > had occasion to do that in a long time), but it turns out when I do this > the lines below it never get executed and when I move them above that > line they seem to work fine so it appears I was wrong about that. I've
I didn't believe you until I had a look into the source. The meat is in SocketServer.py: class BaseRequestHandler: [snip] def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server try: self.setup() self.handle() self.finish() finally: sys.exc_traceback = None # Help garbage collection def setup(self): pass def handle(self): pass def finish(self): pass As you can see this doesn't use __init__() just to set up the instance, it makes it the only method that is called by client code. That's an unusual design decision, to say the least. > tried typing many variants of "python class extend constructor" into > google over the last few days but I'm damned if I can find the docs > explaining this. I'm sure I found them several years back when I first > too up python, maybe by google-fu is on the wane! > > Anyway, that's not my main question, this is... The extra names that I > pass to functools.partial seem to be bound permanently into the > namespace of my class now i.e. I can reference them as 'api_call' and > 'paths' anywhere in the classes' methods as opposed to having to assign > them in the constructor and reference them as 'self.api_call' and > 'self.paths'. I'm not 100% how that's working but in practical terms it > suggests to two lines assigning those names to data attributes are > redundant as I can access them anywhere anyway. Indeed, I've commented > them out and my app still seems to work fine so... > > Question A) Are there any good reasons why I shouldn't just do that? > (other than B!) No. Use either class B(A): path = ... or class B(A): def __init__(self, path, *args, **kw): self.path = path A.__init__(self, *args, **kw) not both. > Question B) The only reason I can think of so far is that I don't have a > clear picture of how those names came to end up in that scope, it seems > very convenient but I'm worried it's black magic of some sort! Could > anyone explain or point me to the right docs please? Python looks for attributes in the instance first, and then in the class as a fallback. You only need to put them in the instance if you expect that you want a different value for every instance. Peter -- http://mail.python.org/mailman/listinfo/python-list