Class extension confusion :(

Peter Otten __peter__ at web.de
Thu Nov 11 09:01:00 CET 2010


r0g wrote:

> On 10/11/10 09:52, Peter Otten wrote:
>> r0g wrote:
>>
>>> I have a subclass of BaseHHTPRequestHandler which uses a dictonary
>>> "paths" and a function "api_call" which are defined in the main
>>> namespace of the module. I'd rather I was able to pass these object to
>>> the constructor and store them as data attributes "self.paths" and
>>> "self.api_call" but I'm not sure how to do that properly. My
>>> understanding is that one may extend a constructor by defining it's
>>> __init__ method, calling the parents constructor and then adding ones
>>> own attributes to taste. What I don't understand is where or how I am
>>> supposed to get these extra constructor arguments into the class given
>>> that I don't instantiate it myself, it is seemingly instantiated by
>>> HTTPServer class that I pass it to e.g.
>>>
>>> httpd = HTTPServer(server_address, PlainAJAXRequestHandler)
>>>
>>> I wondered if I ought to instantiate an instance of
>>> PlainAJAXRequestHandler, set the attributes (either manually or by
>>> extending it's constructor) and pass that to HTTPServer but I figured it
>>> expects a class not an instance as it probably wants to spawn one
>>> instance for each request so that would be a non starter. Might I need
>>> to subclass HTTPServer, find the bit that instantiates the request
>>> handler and override that so it passes it's constructor more parameters?
>>> Right now I'm pretty confused, can somebody please tell me how I might
>>> accomplish this, what I'm failing to grasp or point me to the docs that
>>> explain it - I've spent the last hour or two plowing through docs to no
>>> avail, I guess it's a case of keyword ignorance on my part! Code
>>> follows...
>>
>> Try passing a factory function instead of a class. Untested:
>>
>> from functools import partial
>>
>> class PlainAJAXRequestHandler(BaseHTTPRequestHandler):
>>      def __init__(self, api_call, paths, *args, **kw):
>>          BaseHTTPRequestHandler.__init__(self, *args, **kw)
>>          self.api_call = api_call
>>          self.paths = paths
>>
>> paths = ...
>> api_call = ...
>>
>> httpd = HTTPServer(
>>      server_address,
>>      partial(PlainAJAXRequestHandler, paths, api_call))
>>
> 
> 
> Great, that looks ideal Peter, thanks very much :)
> 
> One more question quick question if you have time... I actually subclass
> the class in question later on to provide an SSL secured connection, is
> it possible (or even advisable) to do the following to spare me having
> to modify the derived classes init (and any subsequent classes' inits)
> too?...
> 
> PlainAJAXRequestHandler = partial(PlainAJAXRequestHandler, paths,
> api_call))
> 
> ^??? Remap name to new extended class
> 
> class SecureAJAXRequestHandler(PlainAJAXRequestHandler):

That's not possible; you are trying to subclass a function. 
What you can do (again untested):

def make_handler_class(paths, api_call):
    class MyHandler(BaseHTTPRequestHandler):
        paths = paths
        api_call = staticmethod(api_call)
    return MyHandler

PlainAJAXRequestHandler = make_handler_class(paths, api_call)

class SecureAJAXRequestHandler(PlainAJAXRequestHandler):
   ...

Peter



More information about the Python-list mailing list