0

This Python 2 example:

class LoggingDict(dict):
    # Simple example of extending a builtin class
    def __setitem__(self, key, value):
        logging.info('Setting %r to %r' % (key, value))
        super(LoggingDict, self).__setitem__(key, value)

and this Python 3 example:

class LoggingDict(dict):
    # Simple example of extending a builtin class
    def __setitem__(self, key, value):
        logging.info('Setting %r to %r' % (key, value))
        super().__setitem__(key, value)

illustrate the fact that Python 2's super requires explicit class and self arguments (but Python 3's doesnt). Why is that? It seems like an irritating limitation.

Brendan
  • 1,995
  • 1
  • 20
  • 35
  • 1
    May be you can find it here what you seek - [Why is Python 3.x's super() magic?](http://stackoverflow.com/questions/19608134/why-is-python-3-xs-super-magic) – AKS Apr 29 '16 at 03:52
  • That doesn't quite answer the question but does provide some useful context to chew over, maybe when I sit down and think about it an answer will present itself. – Brendan Apr 29 '16 at 05:21
  • In fact, I think that question does hint at the answer: it's because 'compile-time magic' is performed, and also in the mention of the fact that `super(self.__class__...` is Bad. This requires some thought! – Brendan Apr 29 '16 at 05:23
  • @Brendan Python3 breaks in some situations, e.g `def __init__(self): mysuper = super; mysuper().__init__()` will not call the parent class `__init__`, yet it's not a `SyntaxError`. In fact I find that the Python3 implementation is too much a hack...I would have rather have `super` as a proper keyword... – Bakuriu Jul 29 '16 at 14:32

1 Answers1

1

The link in AKS' comment provides the answer here:

Lets say in the Python 2 example I thought "I don't like that explicit class reference. What if I change the name of the class or move this code and forget to update it?". Lets say I thought, a-ha, I'll replace the explicit class name with self.__class__ and wrote:

class LoggingDict(dict):
    # Simple example of extending a builtin class
    def __setitem__(self, key, value):
        logging.info('Setting %r to %r' % (key, value))
        super(self.__class__, self).__setitem__(key, value)

Now I create a subclass called SpecialisedLoggingDict of LoggingDict (which doesn't override __setitem__), instantiate it and call __setitem__ on it.

Now self refers to an instance of SpecialisedLoggingDict, so the super returns LoggingDict, and we go straight back into LoggingDict.__setitem__, entering infinite recursion.

The essential point is that in Python 2 a method doesn't really know which class it was defined in, it only knows the class of the instance on which it's being called. Python 3 does compile-time "magic", adding a __class__ cell to functions so that super() can be used without the explicit class reference.

Brendan
  • 1,995
  • 1
  • 20
  • 35