473,563 Members | 2,667 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

super, decorators and gettattribute

Hello all,

I am playing around w/ Python's object system and decorators and I
decided to write (as an exercise) a decorator that (if applied to a
method) would call the superclass' method of the same name before
doing anything (initially I wanted to do something like CLOS
[1] :before and :end methods, but that turned out to be too
difficult).

However, I cannot get it right (specially, get rid of the eval). I
suspect that I may be misunderstandin g something happening between
super objects and __getattribute_ _ methods.

Here's my code:

def endmethod(fun):
"""Decorato r to call a superclass' fun first.

If the classes child and parent are defined as below, it should
work like:
>>x = child()
x.foo()
I am parent's foo
I am child's foo.
"""
name = fun.__name__
def decorated(self, *args, **kwargs):
try:
super_object = super(self.__cl ass__, self)

# now I want to achieve something equivalent to calling
# parent.foo(*arg s, **kwargs)
# if I wanted to limit it only to this example

# this doesn't work: in the example, it calls child's foo,
# entering in an eternal loop (instead of calling parent's
# foo, as I would expect).

# super_object.__ getattribute__( name)(*args, **kwargs)

# this does work, but I feel it's ugly
eval('super_obj ect.%s(*args, **kwargs)' % name)
except AttributeError:
pass # if parent doesn't implement fun, we don't care
# about it
return fun(self, *args, **kwargs) # hopefully none

decorated.__nam e__ = name
return decorated
class parent(object):
def foo(self):
print 'I am parent\'s foo'

class child(parent):
@endmethod
def foo(self):
print "I am foo\'s foo."

if __name__=='__ma in__':
x = child()
x.foo()

Can anybody tell me how to call a superclass method knowing its name?

Thanks in advance,
-- Richard

[1] http://en.wikipedia.org/wiki/Common_Lisp_Object_System
Jan 12 '08 #1
18 2481
On Jan 12, 7:45 pm, Richard Szopa <ryszard.sz...@ gmail.comwrote:
doing anything (initially I wanted to do something like CLOS
[1] :before and :end methods, but that turned out to be too
difficult).
Erm, I meant :before and :after methods.

-- Richard

Jan 12 '08 #2
On Sat, 12 Jan 2008 10:45:25 -0800 (PST) Richard Szopa <ry***********@ gmail.comwrote:
Hello all,

I am playing around w/ Python's object system and decorators and I
decided to write (as an exercise) a decorator that (if applied to a
method) would call the superclass' method of the same name before
doing anything (initially I wanted to do something like CLOS
[1] :before and :end methods, but that turned out to be too
difficult).

However, I cannot get it right (specially, get rid of the eval). I
suspect that I may be misunderstandin g something happening between
super objects and __getattribute_ _ methods.

Here's my code:

def endmethod(fun):
"""Decorato r to call a superclass' fun first.

If the classes child and parent are defined as below, it should
work like:
>>x = child()
>>x.foo()
I am parent's foo
I am child's foo.
"""
name = fun.__name__
def decorated(self, *args, **kwargs):
try:
super_object = super(self.__cl ass__, self)
There's an apparently common bug here: you don't want to pass super
self.__class__, but the class that the method is bound to. The two
aren't the same, as an instance of a subclass will have the subclass
as self.__class__, and not the current class. So super will return the
current class or a subclass of it, meaning (since you invoked this
method from self) you'll wind up invoking this method recursively.
All of which means your decorator is probably going to have to take
the class as an argument.
# now I want to achieve something equivalent to calling
# parent.foo(*arg s, **kwargs)
# if I wanted to limit it only to this example

# this doesn't work: in the example, it calls child's foo,
# entering in an eternal loop (instead of calling parent's
# foo, as I would expect).

# super_object.__ getattribute__( name)(*args, **kwargs)

# this does work, but I feel it's ugly
eval('super_obj ect.%s(*args, **kwargs)' % name)
except AttributeError:
pass # if parent doesn't implement fun, we don't care
# about it
return fun(self, *args, **kwargs) # hopefully none

decorated.__nam e__ = name
return decorated
class parent(object):
def foo(self):
print 'I am parent\'s foo'

class child(parent):
@endmethod
def foo(self):
print "I am foo\'s foo."

if __name__=='__ma in__':
x = child()
x.foo()

Can anybody tell me how to call a superclass method knowing its name?
The same way you call any object's methods if you know it's name":

getattr(super_o bject, name)(*args, **kwargs)

The code seems to work the way you want:
>>x.foo()
I am parent's foo
I am foo's foo.

<mike
--
Mike Meyer <mw*@mired.or g> http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.
Jan 12 '08 #3
On Jan 12, 9:47 pm, Mike Meyer <mwm-keyword-python.b4b...@m ired.org>
wrote:
The same way you call any object's methods if you know it's name":

getattr(super_o bject, name)(*args, **kwargs)
Thanks a lot for your answer!

However, I am very surprised to learn that

super_object.__ getattr__(name) (*args, **kwargs)

getattr(super_o bject, name)(*args, **kwargs)

are not equivalent. This is quite odd, at least when with len()
and .__len__, str() and .__str__. Do you maybe know what's the
rationale behind not following that convention by getattr?

Best regards,

-- Richard
Jan 12 '08 #4
On Sat, 12 Jan 2008 15:47:05 -0500, Mike Meyer wrote:
There's an apparently common bug here: you don't want to pass super
self.__class__, but the class that the method is bound to.
Given an instance method, is it possible to easily determine what class
it is defined in?

I thought the im_class attribute might do it, but it apparently just
points to self.__class__.
>>class Foo(object):
.... def foo(self):
.... pass
....
>>class Bar(Foo):
.... def bar(self):
.... pass
....
>>Bar().bar.im_ class # expecting Bar
<class '__main__.Bar'>
>>Bar().foo.im_ class # hoping for Foo
<class '__main__.Bar'>

--
Steven
Jan 13 '08 #5
On Sat, 12 Jan 2008 14:23:52 -0800, Richard Szopa wrote:
However, I am very surprised to learn that

super_object.__ getattr__(name) (*args, **kwargs)

getattr(super_o bject, name)(*args, **kwargs)

are not equivalent. This is quite odd, at least when with len()
and .__len__, str() and .__str__. Do you maybe know what's the
rationale behind not following that convention by getattr?
I think you are confusing `__getattr__` and `__getattribute __` here!
`getattr()` maps to `__getattr__()` , it's `__getattribute __` that's
different.

Ciao,
Marc 'BlackJack' Rintsch
Jan 13 '08 #6
On Jan 13, 8:59 am, Marc 'BlackJack' Rintsch <bj_...@gmx.net wrote:
On Sat, 12 Jan 2008 14:23:52 -0800, Richard Szopa wrote:
However, I am very surprised to learn that
super_object.__ getattr__(name) (*args, **kwargs)
getattr(super_o bject, name)(*args, **kwargs)
are not equivalent. This is quite odd, at least when with len()
and .__len__, str() and .__str__. Do you maybe know what's the
rationale behind not following that convention by getattr?

I think you are confusing `__getattr__` and `__getattribute __` here!
`getattr()` maps to `__getattr__()` , it's `__getattribute __` that's
different.
Well, in my code calling super_object.__ getattr__(name) (*args,
**kwargs) and getattr(super_o bject, name)(*args, **kwargs) gives
*different* effects (namely, the latter works, while the former
doesn't). That kinda suggests that they don't map to each other :-).
And that makes me feel confused.

Cheers,

-- Richard

Jan 13 '08 #7
On Jan 13, 1:51 pm, Richard Szopa <ryszard.sz...@ gmail.comwrote:
On Jan 13, 8:59 am, Marc 'BlackJack' Rintsch <bj_...@gmx.net wrote:
On Sat, 12 Jan 2008 14:23:52 -0800, Richard Szopa wrote:
However, I am very surprised to learn that
super_object.__ getattr__(name) (*args, **kwargs)
getattr(super_o bject, name)(*args, **kwargs)
are not equivalent. This is quite odd, at least when with len()
and .__len__, str() and .__str__. Do you maybe know what's the
rationale behind not following that convention by getattr?
I think you are confusing `__getattr__` and `__getattribute __` here!
`getattr()` maps to `__getattr__()` , it's `__getattribute __` that's
different.

Well, in my code calling super_object.__ getattr__(name) (*args,
**kwargs) and getattr(super_o bject, name)(*args, **kwargs) gives
*different* effects (namely, the latter works, while the former
doesn't). That kinda suggests that they don't map to each other :-).
And that makes me feel confused.

Cheers,

-- Richard
They do, except for when it comes to what super(..) returns. It isn't
really an object in the sense that they're presented in the tutorial,
but rather a sort of proxy to the methods in the ancestor classes of
the concrete object (self), relative to the current method's class. I
can't imagine that sentence would ease any confusion however, suffice
it to say that you have to call getattr(super(. .), 'name') instead of
super(..).__get attr__('name') and you have to call super(..).__len __()
instead of len(super(..)) -- I can't imagine that lessens any
confusion either :-/

super(..) is designed to handle situations like this correctly

class Root(object):
n = 1

class Left(Root):
def foo(self):
print 'n =', self.n
print 'super n = ', super(Left, self).n

class Right(Root):
n = 2

class Leaf(Left,Right ):
n = 3

x = Leaf()
x.foo()

the correct output is

n = 3
super n = 2
-- bjorn
Jan 13 '08 #8
On Jan 13, 3:31 pm, thebjorn <BjornSteinarFj eldPetter...@gm ail.com>
wrote:
They do, except for when it comes to what super(..) returns. It isn't
really an object in the sense that they're presented in the tutorial,
but rather a sort of proxy to the methods in the ancestor classes of
the concrete object (self), relative to the current method's class. I
can't imagine that sentence would ease any confusion however, suffice
it to say that you have to call getattr(super(. .), 'name') instead of
super(..).__get attr__('name') and you have to call super(..).__len __()
instead of len(super(..)) -- I can't imagine that lessens any
confusion either :-/
Surprisingly, I think your first sentence *does* make something more
clear. Let me check if I understand it right: when we call a method on
super(Foo, self) it is as if we were calling call-next-method in
Common Lisp or Dylan (i.e. the method of the class on the right of Foo
in self.mro()). This however does not imply for super to have its dict
the same as the class on the right of Foo---it remains the same as
self's dict.

However, there's one piece that doesn't completely fit to the puzzle:
why does getattr work? The help says:

getattr(...)
getattr(object, name[, default]) -value

Get a named attribute from an object; getattr(x, 'y') is
equivalent to x.y.
When a default argument is given, it is returned when the
attribute doesn't
exist; without it, an exception is raised in that case.

Does it work on the basis that "getattr(x, 'y') is equivalent to x.y"?
What is then a "named attribute for an object" in Python? It seems not
to be equivalent to the value of the item whose name is 'y' in the
object's class __dict__...

Cheers,

-- Richard
Jan 14 '08 #9
On Jan 14, 1:41 pm, Richard Szopa <ryszard.sz...@ gmail.comwrote:
However, there's one piece that doesn't completely fit to the puzzle:
why does getattr work? The help says:

getattr(...)
getattr(object, name[, default]) -value

Get a named attribute from an object; getattr(x, 'y') is
equivalent to x.y.
When a default argument is given, it is returned when the
attribute doesn't
exist; without it, an exception is raised in that case.

Does it work on the basis that "getattr(x, 'y') is equivalent to x.y"?
What is then a "named attribute for an object" in Python? It seems not
to be equivalent to the value of the item whose name is 'y' in the
object's class __dict__...

Cheers,

-- Richard
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
Jan 14 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2050
by: Michael Sparks | last post by:
Anyway... At Europython Guido discussed with everyone the outstanding issue with decorators and there was a clear majority in favour of having them, which was good. From where I was sitting it looked like about 20:20 split on the following syntaxes: 1 def func(arg1, arg2, arg3) : function... 2 def func(arg1, arg2, arg3):...
17
1756
by: daishi | last post by:
For what it's worth: As far as I know, the proposed @decorator syntax will be the first time that two logical lines of python with the same indentation will not be independent of one another. Previously, when looking at: some_python(code) and_some_more = stuff there was no need to look at the the first line in order to know what
4
1477
by: RebelGeekz | last post by:
Just my humble opinion: def bar(low,high): meta: accepts(int,int) returns(float) #more code Use a metadata section, no need to introduce new messy symbols, or mangling our beloved visual cleanliness of python.
2
1699
by: Guido van Rossum | last post by:
Robert and Python-dev, I've read the J2 proposal up and down several times, pondered all the issues, and slept on it for a night, and I still don't like it enough to accept it. The only reason to accept it would be to pacify the supporters of the proposal, and that just isn't a good enough reason in language design. However, it got...
0
2331
by: Anthony Baxter | last post by:
To go along with the 2.4a3 release, here's an updated version of the decorator PEP. It describes the state of decorators as they are in 2.4a3. PEP: 318 Title: Decorators for Functions and Methods Version: $Revision: 1.34 $ Last-Modified: $Date: 2004/09/03 09:32:50 $ Author: Kevin D. Smith, Jim Jewett, Skip Montanaro, Anthony Baxter
9
1701
by: Paul Rubin | last post by:
I'm trying the super() function as described in Python Cookbook, 1st ed, p. 172 (Recipe 5.4). class A(object): def f(self): print 'A' class B(object): def f(self):
11
2083
by: Helmut Jarausch | last post by:
Hi, are decorators more than just syntactic sugar in python 2.x and what about python 3k ? How can I find out the predefined decorators? Many thanks for your help, Helmut Jarausch
2
1942
by: Andrew West | last post by:
Probably a bit of weird question. I realise decorators shouldn't be executed until the function they are defined with are called, but is there anyway for me to find all the decorates declared in a file when I import it? Or perhaps anyway to find the decorators by loading the file by other methods (with out simply parsing it by hand). ...
12
344
by: iu2 | last post by:
Hi I'm trying to make a method call automatically to its super using this syntax: class A: chained = def pr(self): print 'Hello from A'
0
7659
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7882
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8103
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7634
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7945
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6244
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5481
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3634
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1194
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.