super, decorators and gettattribute
Richard Szopa
ryszard.szopa at gmail.com
Mon Jan 14 17:47:36 EST 2008
On Jan 14, 1:53 pm, Michele Simionato <michele.simion... at gmail.com>
wrote:
> I really need to publish this one day or another, since these
> questions
> about super keeps coming out:
>
> http://www.phyast.pitt.edu/~micheles/python/super.html
Thanks, Michele! Your essay was enlightening [2]. Specially if you
take in account super's documentation is slightly outdated :).
I also read Raymond Hettinger's article about descriptors (which you
mention, but don't link to!) and decided to use them to reimplement
methods that always call their superclass [1] method of the same name.
Could you tell me what are the pros and cons of the two approaches
(i.e. writing a decorator function and a decorator descriptor class)?
The former gives slightly shorter code, while the second gives access
to the original function and I somehow feel it is more... classy :)
[code follows]
Cheers,
-- Richard
[1] By which I mean the first class in their MRO.
[2] I also found some other papers of yours about the "not for the
faint of heart" corners of Python: MRO, metaclasses, class
memoization, etc. and they were most enjoyable and interesting.
def callingprevious1(fun):
"""Decorator to call a superclass' fun first. Decorator function
approach.
>>> class parent(object):
... def foo(self):
... print "I am foo of parent"
...
>>> class child(parent):
... @callingprevious1
... def foo(self):
... print "I am foo of child"
...
>>> x = child()
>>> x.foo()
I am foo of parent
I am foo of child
>>> child.foo(x)
I am foo of parent
I am foo of child
"""
name = fun.__name__
def decorated(self, *args, **kwargs):
try:
super_object = super(self.__class__, self)
getattr(super_object, name)(*args, **kwargs)
except AttributeError:
pass # if parent doesn't implement fun, we don't care
# about it
return fun(self, *args, **kwargs) # hopefully None
decorated.__name__ = name
return decorated
class callingprevious(object):
"""
Decorator making the defined method call the method of the first
superclass in mro at the beginning. Descriptor approach.
>>> class parent(object):
... def foo(self):
... print "I am foo of parent"
...
>>> class child(parent):
... @callingprevious
... def foo(self):
... print "I am foo of child"
...
>>> x = child()
>>> x.foo()
I am foo of parent
I am foo of child
>>> child.foo(x)
I am foo of parent
I am foo of child
"""
def __init__(self, initval):
self.name = initval.__name__
self.__combine_methods(initval)
def __combine_methods(self, val):
self.val = val
def with_parent(obj, *args, **kwargs):
try:
parent_method = getattr(super(type(obj), obj),
self.val.__name__)
except AttributeError:
pass
else:
parent_method(*args, **kwargs)
return self.val(obj, *args, **kwargs)
with_parent.__name__ = self.val.__name__
self.to_return = with_parent
def __get__(self, obj, objtype):
from types import MethodType
# btw, is it anyhow better than just returning the function?
return MethodType(self.to_return, obj, objtype)
def __set__(self, obj, val):
self.__combine_methods(val)
More information about the Python-list
mailing list