Search code examples
pythonpython-2.7static-methodssuper

super() and @staticmethod interaction


Is super() not meant to be used with staticmethods?

When I try something like

class First(object):
  @staticmethod
  def getlist():
    return ['first']

class Second(First):
  @staticmethod
  def getlist():
    l = super(Second).getlist()
    l.append('second')
    return l

a = Second.getlist()
print a

I get the following error

Traceback (most recent call last):
  File "asdf.py", line 13, in <module>
    a = Second.getlist()
  File "asdf.py", line 9, in getlist
    l = super(Second).getlist()
AttributeError: 'super' object has no attribute 'getlist'

If I change the staticmethods to classmethods and pass the class instance to super(), things work fine. Am I calling super(type) incorrectly here or is there something I'm missing?


Solution

  • The short answer to

    Am I calling super(type) incorrectly here or is there something I'm missing?

    is: yes, you're calling it incorrectly... AND (indeed, because) there is something you're missing.

    But don't feel bad; this is an extremely difficult subject.

    The documentation notes that

    If the second argument is omitted, the super object returned is unbound.

    The use case for unbound super objects is extremely narrow and rare. See these articles by Michele Simionato for his discussion on super():

    Also, he argues strongly for removing unbound super from Python 3 here.

    I said you were calling it "incorrectly" (though correctness is largely meaningless without context, and a toy example doesn't give much context). Because unbound super is so rare, and possibly just flat-out unjustified, as argued by Simionato, the "correct" way to use super() is to provide the second argument.

    In your case, the simplest way to make your example work is

    class First(object):
      @staticmethod
      def getlist():
        return ['first']
    
    class Second(First):
      @staticmethod
      def getlist():
        l = super(Second, Second).getlist()  # note the 2nd argument
        l.append('second')
        return l
    
    a = Second.getlist()
    print a
    

    If you think it looks funny that way, you're not wrong. But I think what most people are expecting when they see super(X) (or hoping for when they try it in their own code) is what Python gives you if you do super(X, X).