superarg: an alternative to super()

I was testing the new functionality of super() in Python 3.0a4, and noted the current "limitations": ------------------------------------------------------------ Test 1 - define method outside class definition
------------------------------------------------------------ Test 2 - Call super() from inner function
------------------------------------------------------------ Not satisfied, I started work on another way to simplify using super(). I call it superarg, and it doesn't have any of the above limitations. It only takes twenty-six lines to implement in Python, and doesn't rely on bytecode hacks or stack frame inspection. What superarg does do is provide a decorator that inserts the super object into the method's argument list, before the self argument. In the following Python-only implementation, correct behavior does depend on using a special metaclass. Here it is, including a test suite (tested in Python 3.0a4): ------------------------------------------------------------ # superarg.py from types import MethodType class superarg_method(): def __init__(self, callable, cls=None): self.callable = callable self.cls = cls def __get__(self, obj, objtype=None): return self if obj is None else MethodType(self, obj) def __call__(self, obj, *args, **kwargs): return self.callable(super(self.cls, obj), obj, *args, **kwargs) def withclass(self, cls): return self.__class__(self.callable, cls) class superarg_classmethod(superarg_method): def __get__(self, obj, objtype=None): return MethodType(self, type(obj) if objtype is None else objtype) class superarg_meta(type): def __init__(cls, name, bases, dict): for name, value in dict.items(): if isinstance(value, superarg_method): type.__setattr__(cls, name, value.withclass(cls)) def __setattr__(cls, name, value): if isinstance(value, superarg_method): value = value.withclass(cls) type.__setattr__(cls, name, value) # implementation ends here - test suite follows: if __name__ == '__main__': class A(metaclass=superarg_meta): def f(self): return 'A(%s)' % (self.name,) @classmethod def cm(cls): return 'A(%s)' % (cls.__name__,) # Standard use class B(A): @superarg_method def f(super, self): return 'B' + super.f() @superarg_classmethod def cm(super, cls): return 'B' + super.cm() # Reference super in inner function class C(A): @superarg_method def f(super, self): def inner(): return 'C' + super.f() return inner() @superarg_classmethod def cm(super, cls): def inner(): return 'C' + super.cm() return inner() # Define functions before class definition @superarg_method def D_f(super, self): return 'D' + super.f() @superarg_classmethod def D_cm(super, cls): return 'D' + super.cm() class D(B, C): def __init__(self, name): self.name = name f = D_f cm = D_cm # Define functions after class definition class E(C, B): def __init__(self, name): self.name = name @superarg_method def E_f(super, self): return 'E' + super.f() @superarg_classmethod def E_cm(super, cls): return 'E' + super.cm() E.f = E_f E.cm = E_cm # Test D d = D('d') assert d.f() == 'DBCA(d)' # Normal method, instance binding assert D.f(d) == 'DBCA(d)' # Normal method, class binding assert d.cm() == 'DBCA(D)' # Class method, instance binding assert D.cm() == 'DBCA(D)' # Class method, class binding # Test E e = E('e') assert e.f() == 'ECBA(e)' assert E.f(e) == 'ECBA(e)' assert e.cm() == 'ECBA(E)' assert E.cm() == 'ECBA(E)' # Test using D's methods in E E.cm = D_cm E.f = D_f assert e.f() == 'DCBA(e)' assert E.f(e) == 'DCBA(e)' assert e.cm() == 'DCBA(E)' assert E.cm() == 'DCBA(E)' # Why not use E.cm = D.cm? Because D.cm returns a bound method # (this would also be the case without using superarg). Instead, # one would need to use E.cm = D.__dict__['cm'] ------------------------------------------------------------ The decorators only need to be applied where necessary. If a method doesn't need the super object, then it doesn't need the decorator. I also tested implementing the decorators in C (as built-in types), which works even better because I was able to put the class fix-ups in type_new and type_setattro. Thus, the special metaclass is no longer needed. The only times it wouldn't work right is if the end-user implemented a metaclass that never calls type's __new__ or __setattr__ methods. Avoiding type.__new__ should be fairly rare, but I'm not sure about __setattr__. I could probably extend the types so users can do their own fix-ups if need be. However, if a user is customizing a class that much, then I wonder if they would make use of superarg anyway. Whether or not there is any perceived value in adding this to a future version of Python, perhaps someone will find it useful enough to add to one of their own projects (and back-porting it to Python 2.x should be fairly simple). -- Anthony Tolle

Sorry, not interested. On Tue, Apr 8, 2008 at 6:55 PM, Anthony Tolle <artomegus@gmail.com> wrote:
-- --Guido van Rossum (home page: http://www.python.org/~guido/)

"Anthony Tolle" <artomegus@gmail.com> wrote in message news:47857e720804081855o53152c27kf8ce5c510bea70dc@mail.gmail.com... |I was testing the new functionality of super() in Python 3.0a4, and | noted the current "limitations": | Whether or not there is any perceived value in adding this to a future | version of Python, perhaps someone will find it useful enough to add | to one of their own projects (and back-porting it to Python 2.x should | be fairly simple). I think the Python cookbook at Oreilly might be a good place for this.

Sorry, not interested. On Tue, Apr 8, 2008 at 6:55 PM, Anthony Tolle <artomegus@gmail.com> wrote:
-- --Guido van Rossum (home page: http://www.python.org/~guido/)

"Anthony Tolle" <artomegus@gmail.com> wrote in message news:47857e720804081855o53152c27kf8ce5c510bea70dc@mail.gmail.com... |I was testing the new functionality of super() in Python 3.0a4, and | noted the current "limitations": | Whether or not there is any perceived value in adding this to a future | version of Python, perhaps someone will find it useful enough to add | to one of their own projects (and back-porting it to Python 2.x should | be fairly simple). I think the Python cookbook at Oreilly might be a good place for this.
participants (3)
-
Anthony Tolle
-
Guido van Rossum
-
Terry Reedy