tags:

views:

107

answers:

6

I'm sorry for my silly question, but... let's suppose I have this classes:

class A():
    msg = 'hehehe'

class B(A):
    msg = 'hohoho'

class C(B):
    pass

and an instance of B or C. So, how to get the variable 'msg' from the parent's class object through this instance? I've tried this:

foo = B() #or C()
bar = super(foo.__class__)
print bar.msg

but got the message: "TypeError: super() argument 1 must be type, not classobj"

A: 

Try with:

class A(object):
    msg = 'hehehe'

EDIT:

For the 'msg' attribute you would need:

foo = B()
bar = super(foo.__class__, foo)
print bar.msg
Olivier
No it does not work. He would get following error: `AttributeError: 'super' object has no attribute 'msg'`.
Felix Kling
Well, i was focusing on the error he mentions: "TypeError: super() argument 1 must be type, not classobj" which disappears if he uses classes derived from "object". It is a good piece of advice anyway to use those new style classes! I edited my answer to include the "msg" attribute.
Olivier
+1  A: 

As msg is a class variable, you can just do:

print C.msg    # prints hohoho

If you overwrite the variable (as you do in class B), you have to find the right parent class. Remember that Python supports multiple inheritance.

But as you define the classes and you now that B inherits from A you can always do this:

class B(A):
    msg = 'hohoho'

    def get_parent_message(self):
       return A.msg

UPDATE:

The most reliable thing would be:

def get_parent_attribute(instance, attribute):
    for parent in instance.__class__.__bases__:
        if attribute in parent.__dict__:
             return parent.__dict__[attribute]

and then:

foo = B()
print get_parent_attribute(foo, 'msg')
Felix Kling
yes, I know. But what if i don't know what exactly parent class of given instance is, and I need to access exactly its 'msg'?
PyNewbie
@PyNewbie: If you don't know the parent class, how do you know that it has a `msg` attribute?
Felix Kling
@PyNewbie: look at my answer: you did it right, but you forgot to use the "new" object class of python; all your classes should inherit from "object" and you'll be fine
Olivier
@PyNewbie: See my updated answer for a more reliable method.
Felix Kling
+1  A: 
foo = B()
print foo.__class__.__bases__[0].msg
// 'hehehe'
KennyTM
And what if the class inherits from multiple classes? Your approach will probably work most of the time, but it is not reliable.
Felix Kling
Thanks. it works fine
PyNewbie
A: 
#for B() you can use __bases__
print foo.__class__.__bases__[0].msg

But this is not gonna be easy when there are multiple base classes and/or the depth of hierarchy is not one.

Amarghosh
+1  A: 

Not sure why you want to do this

>>> class A(object):
...     msg = 'hehehe'
... 
>>> class B(A):
...     msg = 'hohoho'
... 
>>> foo=B()
>>> foo.__class__.__mro__[1].msg
'hehehe'
>>> 
gnibbler
+4  A: 

You actually want to use

class A(object):
    ...
...
b = B()
bar = super(b.__class__, b)
print bar.msg

Base classes must be new-style classes (inherit from object)

Tim Dumol
That's the way... i guess
mshsayem