On Fri, 2011-05-27 at 15:05 +0000, Duncan Booth wrote: > sturlamolden <sturlamol...@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 r...@rfk.id.au | http://www.rfk.id.au/ramblings/gpg/ for details
signature.asc
Description: This is a digitally signed message part
-- http://mail.python.org/mailman/listinfo/python-list