Class extension confusion :(
Peter Otten
__peter__ at web.de
Thu Nov 11 04:34:22 EST 2010
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
More information about the Python-list
mailing list