super with only one argument

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven Bethard

    #1

    super with only one argument

    When would you call super with only one argument? The only examples I
    can find of doing this are in the test suite for super. Playing around
    with it:

    py> class A(object):
    .... x = 'a'
    ....
    py> class B(A):
    .... x = 'b'
    ....
    py> s = super(B)
    py> s.x
    Traceback (most recent call last):
    File "<interacti ve input>", line 1, in ?
    AttributeError: 'super' object has no attribute 'x'

    So I can't access class attributes with a single-argument super.

    You can see that there are some interesting attributes on a super object:

    py> for name in dir(s):
    .... if not hasattr(object, name):
    .... print name, getattr(s, name)
    ....
    __get__ <method-wrapper object at 0x011FD050>
    __self__ None
    __self_class__ None
    __thisclass__ <class '__main__.B'>

    Looks like I can call the descriptor machinery directly to get an attribute:

    py> s.__get__(B).x
    'a'
    py> s.__get__(B, B()).x
    'a'

    But this doesn't seem horribly useful. And __self__, __self_class__ and
    __thisclass__ are readonly, so I can't bind a super object to an
    instance once it's been created.

    So what's the use case?

    Thanks in advance,

    STeVe

    P.S. The context here is that I'm trying to submit a patch to clarify
    the docs on super a bit. But I realized that I don't actually
    understand its behavior with only a single argument...
  • Michele Simionato

    #2
    Re: super with only one argument

    I asked myself the same question and I am not convinced
    that using 'super' with one argument really makes sense
    (i.e. IMO it is more a liability than an asset). BTW, I have a set
    of notes on the tricky aspects of 'super' you may be interested in.

    Michele Simionato

    Comment

    • John Roth

      #3
      Re: super with only one argument

      "Michele Simionato" <michele.simion ato@gmail.com> wrote in message
      news:1110824920 .833833.164930@ o13g2000cwo.goo glegroups.com.. .[color=blue]
      >I asked myself the same question and I am not convinced
      > that using 'super' with one argument really makes sense
      > (i.e. IMO it is more a liability than an asset). BTW, I have a set
      > of notes on the tricky aspects of 'super' you may be interested in.
      >
      > Michele Simionato[/color]

      Wouldn't you use it to access the overridden version
      of a static method?

      John Roth[color=blue]
      >[/color]

      Comment

      • Michele Simionato

        #4
        Re: super with only one argument

        No, you should use the version with two arguments for that.
        The second argument would be a class however, not an instance.
        Example:

        class C(object):
        @staticmethod
        def f():
        print "C.f"

        class D(C):
        @staticmethod
        def f():
        print "D.f"
        super(D, D).f()

        D.f()

        Just using super(D).f() would not work. ``super`` with only one
        argument is
        a recipe for headaches.

        Michele Simionato

        Comment

        • Greg Chapman

          #5
          Re: super with only one argument

          Steven Bethard wrote:
          [color=blue]
          > When would you call super with only one argument? The only examples
          > I can find of doing this are in the test suite for super.
          >[/color]

          I think it's to allow something like this:

          class A(B, C):
          __super = super(A)
          def foo(self):
          return self.__super.fo o()

          This allows you to rename A and only have to change one super call to
          reflect the new name.

          ---
          Greg Chapman

          Comment

          • Greg Chapman

            #6
            Re: super with only one argument

            Greg Chapman wrote:
            [color=blue]
            > Steven Bethard wrote:
            >[color=green]
            > > When would you call super with only one argument? The only examples
            > > I can find of doing this are in the test suite for super.
            > >[/color]
            >
            > I think it's to allow something like this:
            >
            > class A(B, C):
            > __super = super(A)
            > def foo(self):
            > return self.__super.fo o()
            >
            > This allows you to rename A and only have to change one super call to
            > reflect the new name.
            >[/color]

            Except that doesn't work unless you use something like the autosuper
            metaclass trick from test_descr.py (since the class A does not yet
            exist where I put that super call). And autosuper has a comment that
            it "only works for dynamic classes" -- not sure that I understand what
            "dynamic" means there.

            In case you haven't guessed by now, I've only used two-arg super in my
            own code.

            ---
            Greg Chapman


            Comment

            • Michele Simionato

              #7
              Re: super with only one argument

              ``super`` with only one argument ("bound" super) is a mess.

              AFAICT ``super(C)`` is intended to be used as an attribute in
              other classes. Then the descriptor magic will automatically convert the

              unbound syntax in the bound syntax. For instance:
              [color=blue][color=green][color=darkred]
              >>> class B(object):[/color][/color][/color]
              .... a = 1[color=blue][color=green][color=darkred]
              >>> class C(B):[/color][/color][/color]
              .... pass[color=blue][color=green][color=darkred]
              >>> class D(C):[/color][/color][/color]
              .... sup = super(C)[color=blue][color=green][color=darkred]
              >>> d = D()
              >>> d.sup.a[/color][/color][/color]
              1

              This works since ``d.sup.a`` calls ``super(C).__ge t__(d,D).a`` which is
              converted to ``super(C, d).a`` and retrieves ``B.a``.

              There is a single use case for the single argument
              syntax of ``super`` that I am aware of, but I think it gives more
              troubles
              than advantages. The use case is the implementation of "autosuper" made

              by Guido on his essay about new-style classes (the one Grep Chapman is
              citing).

              The idea there is to use the unbound super objects as private
              attributes. For instance, in our example, we could define the
              private attribute ``__sup`` in the class ``C`` as the unbound
              super object ``super(C)``:
              [color=blue][color=green][color=darkred]
              >>> C._C__sup = super(C)[/color][/color][/color]

              With this definition inside the methods the syntax
              ``self.__sup.me th(arg)`` can be used
              as an alternative to ``super(C, self).meth(arg) ``, and the advantage is

              that you avoid to repeat the name of the class in the calling
              syntax, since that name is hidden in the mangling mechanism of
              private names. The creation of the ``__sup`` attributes can be hidden
              in a metaclass and made automatic. So, all this seems to work: but
              actually this is *not* the case.

              Things may wrong in various case, for instance for classmethods,
              as in this example::

              #<ex1.py>

              class B(object):
              def __repr__(self):
              return '<instance of %s>' % self.__class__. __name__
              @classmethod
              def meth(cls):
              print "B.meth(%s) " % cls

              class C(B):
              @classmethod
              def meth(cls):
              print "C.meth(%s) " % cls
              cls.__super.met h()

              C._C__super = super(C)

              class D(C):
              pass

              D._D__super = super(D)


              d=D()

              d.meth()

              #</ex1.py>

              The last line raises an ``AttributeErro r: 'super' object has no
              attribute
              'meth'.``

              So, using a ``__super`` unbound super object is not a robust solution
              (notice that everything would work by substituting
              ``self.__super. meth()``
              with ``super(C,self) .meth()``. There are other ways to avoid repeating
              the class name, see for instance my cookbook recipe, which will also be
              in the printed version.

              If it was me, I would just remove the single argument syntax of
              ``super``,
              making it illegal. But this would probably break someone code, so
              I don't think it will ever happen. Another solution would be just to
              deprecate it. There is no need for this syntax, one can always
              circumvent
              it. Also, notice that the unbound form of ``super`` does
              not play well with pydoc.
              The problems is still there in Python 2.4 (see bug report SF729103)
              [color=blue][color=green][color=darkred]
              >>> class B(object): pass[/color][/color][/color]
              ....[color=blue][color=green][color=darkred]
              >>> class C(B):[/color][/color][/color]
              .... s=super(B)
              ....[color=blue][color=green][color=darkred]
              >>> help(C)[/color][/color][/color]
              Traceback (most recent call last):
              ...
              ... lots of stuff here
              ...
              File "/usr/lib/python2.4/pydoc.py", line 1290, in docother
              chop = maxlen - len(line)
              TypeError: unsupported operand type(s) for -: 'type' and 'int'

              Michele Simionato

              Comment

              Working...