Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #6440

Re: Python's super() considered super!

Subject Re: Python's super() considered super!
From Ryan Kelly <ryan@rfk.id.au>
References <1f0d88bd-e2e6-4780-9d9e-784fb3f53837@k3g2000prl.googlegroups.com> <1632c707-3660-4248-97c4-3033c269574b@w21g2000yqm.googlegroups.com> <Xns9EF2A3A4CEB06duncanbooth@127.0.0.1>
Date 2011-05-28 09:57 +1000
Newsgroups comp.lang.python
Message-ID <mailman.2181.1306540687.9059.python-list@python.org> (permalink)

Show all headers | View raw


[Multipart message — attachments visible in raw view] - view raw

On Fri, 2011-05-27 at 15:05 +0000, Duncan Booth wrote:
> sturlamolden <sturlamolden@yahoo.no> wrote:
> > I really don't like the Python 2 syntax of super, as it violates
> > the DRY principle: Why do I need to write super(type(self),self)
> > when super() will do? Assuming that 'self' will always be named
> > 'self' in my code, I tend to patch __builtins__.super like this:
> > 
> > import sys
> > def super():
> >     self = sys._getframe().f_back.f_locals['self']
> >     return __builtins__.super(type(self),self)
> > 
> > This way the nice Python 3.x syntax can be used in Python 2.x.
> > 
> > 
> Oh dear, you haven't thought this one through.
>
> ...snip...
>
> >>> C().foo()
> ... infinite recursion follows ...
> 
> Oops. There's a reason why Python 2 requires you to be explicit about 
> the class; you simply cannot work it out automatically at run time. 
> Python 3 fixes this by working it out at compile time, but for Python 2 
> there is no way around it.

Oh?  There's not much that can't be done at runtime if you're willing to
work hard enough.  Let me propose the following awful awful hack:


  import sys

  _builtin_super = __builtins__.super

  _sentinel = object()

  def _auto_super(typ=_sentinel,type_or_obj=_sentinel):
      """Automagically call correct super() at runtime"""
      #  Infer the correct call if used without arguments.
      if typ is _sentinel:
          # We'll need to do some frame hacking.
          f = sys._getframe(1)
          # Get the first positional argument of the function.
          type_or_obj = f.f_locals[f.f_code.co_varnames[0]]
          # Get the MRO for investigation
          try:
              mro = type_or_obj.__mro__
          except AttributeError:
              try:
                  mro = type_or_obj.__class__.__mro__
              except AttributeError:
                  raise RuntimeError("super() used with old-style class")
          #  Now, find the class owning the currently-executing method.
          for typ in mro:
              for meth in typ.__dict__.itervalues():
                  if not isinstance(meth,type(_auto_super)):
                      continue
                  if meth.func_code is f.f_code:
                      # Aha!  Found you.
                      break
              else:
                  continue
              break
          else:
              raise RuntimeError("super() called outside a method")
      #  Now just dispatch to builtin super.
      if type_or_obj is not _sentinel:
          return _builtin_super(typ,type_or_obj)
      return _builtin_super(typ)


Now, try is with the following:

    class Base(object):
        def hello(self,msg):
            print "hello", msg

    class Sub1(Base):
        def hello(self,msg):
            print "gunna say it"
            super().hello(msg)

    class Sub2(Base):
        def hello(self,msg):
            print "yes I am"
            super().hello(msg)

    class Diamond(Sub1,Sub2):
        def hello(self,msg):
            print "here we go..."
            super().hello(msg)

    d = Diamond()
    d.hello("autosuper!")


And you get the expected output:

    here we go...
    gunna say it
    yes I am
    hello autosuper!


There may well be some cases where this breaks down, but it seems to do
the right thing in simple cases.


Not that I'm recommending anyone use this, of course...




   Ryan


-- 
Ryan Kelly
http://www.rfk.id.au  |  This message is digitally signed. Please visit
ryan@rfk.id.au        |  http://www.rfk.id.au/ramblings/gpg/ for details

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Python's super() considered super! Raymond Hettinger <python@rcn.com> - 2011-05-26 09:31 -0700
  Re: Python's super() considered super! Raymond Hettinger <python@rcn.com> - 2011-05-26 09:39 -0700
    Re: Python's super() considered super! Dotan Cohen <dotancohen@gmail.com> - 2011-05-26 21:13 +0300
    Re: Python's super() considered super! Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-26 12:38 -0600
    Re: Python's super() considered super! Dotan Cohen <dotancohen@gmail.com> - 2011-05-26 21:56 +0300
    Re: Python's super() considered super! Terry Reedy <tjreedy@udel.edu> - 2011-05-26 16:15 -0400
  Re: Python's super() considered super! Ben Finney <ben+python@benfinney.id.au> - 2011-05-27 11:39 +1000
    Re: Python's super() considered super! Raymond Hettinger <python@rcn.com> - 2011-05-27 00:16 -0700
      Re: Python's super() considered super! Ben Finney <ben+python@benfinney.id.au> - 2011-05-27 18:49 +1000
        Re: Python's super() considered super! Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-27 10:37 +0000
          Re: Python's super() considered super! Duncan Booth <duncan.booth@invalid.invalid> - 2011-05-27 10:53 +0000
            Re: Python's super() considered super! Ethan Furman <ethan@stoneleaf.us> - 2011-05-27 10:42 -0700
              Re: Python's super() considered super! Duncan Booth <duncan.booth@invalid.invalid> - 2011-05-30 09:18 +0000
    RE: Python's super() considered super! "Prasad, Ramit" <ramit.prasad@jpmchase.com> - 2011-05-27 14:10 -0400
    Re: Python's super() considered super! Chris Angelico <rosuav@gmail.com> - 2011-05-28 04:40 +1000
  Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 07:27 -0700
    Re: Python's super() considered super! Mel <mwilson@the-wire.com> - 2011-05-27 10:33 -0400
      Re: Python's super() considered super! Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-27 14:49 +0000
        Re: Python's super() considered super! harrismh777 <harrismh777@charter.net> - 2011-05-27 10:07 -0500
    Re: Python's super() considered super! Duncan Booth <duncan.booth@invalid.invalid> - 2011-05-27 15:05 +0000
      Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 08:24 -0700
      Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 08:31 -0700
        Re: Python's super() considered super! Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-27 16:06 +0000
          Re: Python's super() considered super! Stefan Behnel <stefan_ml@behnel.de> - 2011-05-27 23:49 +0200
            Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 16:57 -0700
              Re: Python's super() considered super! Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-05-28 07:29 +0200
          Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 17:04 -0700
      Re: Python's super() considered super! Ryan Kelly <ryan@rfk.id.au> - 2011-05-28 09:57 +1000
    Re: Python's super() considered super! sturlamolden <sturlamolden@yahoo.no> - 2011-05-27 08:11 -0700
  Re: Python's super() considered super! Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-27 12:31 -0600
  Re: Python's super() considered super! Chris Angelico <rosuav@gmail.com> - 2011-05-28 04:46 +1000
    Re: Python's super() considered super! John Nagle <nagle@animats.com> - 2011-05-27 13:47 -0700
  Re: Python's super() considered super! Ethan Furman <ethan@stoneleaf.us> - 2011-05-27 15:24 -0700

csiph-web