super() in class defs?

Carl Banks pavlovevidence at gmail.com
Wed May 25 19:26:34 EDT 2011


On Wednesday, May 25, 2011 10:54:11 AM UTC-7, Jess Austin wrote:
> I may be attempting something improper here, but maybe I'm just going
> about it the wrong way. I'm subclassing
> http.server.CGIHTTPRequestHandler, and I'm using a decorator to add
> functionality to several overridden methods.
> 
> def do_decorate(func):
> .   def wrapper(self):
> .       if appropriate():
> .           return func()
> .       complain_about_error()
> .   return wrapper
> 
> class myHandler(CGIHTTPRequestHandler):
> .   @do_decorate
> .   def do_GET(self):
> .       return super().do_GET()
> .   # also override do_HEAD and do_POST
> 
> My first thought was that I could just replace that whole method
> definition with one line:
> 
> class myHandler(CGIHTTPRequestHandler):
> .   do_GET = do_decorate(super().do_GET)
> 
> That generates the following error:
> 
> SystemError: super(): __class__ cell not found
> 
> So I guess that when super() is called in the context of a class def
> rather than that of a method def, it doesn't have the information it
> needs.

Right.  Actually the class object itself doesn't even exist yet when super() is invoked.  (It won't be created until after the end of the class statement block.)

> Now I'll probably just say:
> 
>     do_GET = do_decorate(CGIHTTPRequestHandler.do_GET)
> 
> but I wonder if there is a "correct" way to do this instead? Thanks!

Well, since the class object isn't created until after the end of the class statement block, it's impossible to invoke super() on the class from inside the block.  So there's only two ways to invoke super(): 1. like you did above, by calling it inside a method, and 2. call it beyond the end of the class statement, like this:

    class myHandler(CGIHTTPRequestHandler):
        pass

    myHandler.do_GET = do_decorate(super(myHandler).do_GET)

I wouldn't call that correct, though.  (I'm not even sure it'll work, since I don't have Python 3 handy to test it, but as far as I can tell it will.)

It's just one of the quirks of Python's type system.

I don't agree with Ian's recommendation not to use super() in general, but I'd probably agree that one should stick to using it only in its intended way (to invoke base-class methods directly).


Carl Banks



More information about the Python-list mailing list