Anurag Sharma
Anurag Sharma

Reputation: 5039

__getattribute__ function to return object value from another class

I have a base class which has 2 attributes which itself are from another class. See the code below

class Base(object):
    def __init__(self, obj1, obj2):
        self.obj1 = obj1
        self.obj2 = obj2

    def __getattribute__(self, name):
        #import pdb; pdb.set_trace()
        if name == 'obj1':
            obj = object.__getattribute__(self, name) #self.obj1.value
            return object.__getattribute__(obj,'value')

class Temp(object):
    def __init__(self, value, type):
        self.value = value
        self.type = type

    def __getattribute__(self, name):
        #if name == 'value':
        #    return object.__getattribute__(self, name)
        if name == 'type':
            return object.__getattribute__(self, name)

if __name__ == "__main__":
    temp_obj1 = Temp(45, type(45))
    temp_obj2 = Temp('string', type('string'))

    base_obj = Base(temp_obj1, temp_obj2)
    print base_obj.obj1
    print base_obj.obj1.type

and its output:-

45
Traceback (most recent call last):
  File "getattr.py", line 29, in <module>
    print base_obj.obj1.type
AttributeError: 'int' object has no attribute 'type'

Basically what I am trying to achieve is I don't have to call base_obj.obj1.value to get the value attribute of obj1 but calling base_obj.obj1 will give the desired result. But at the same time I am be able to call some function or property of obj1 like base_obj.obj1.type or base_obj.obj1.some_method()

But as you can see I am getting the error. How can I achieve the desired functionality

Upvotes: 0

Views: 1582

Answers (1)

BrenBarn
BrenBarn

Reputation: 251365

If I understand your question right, you can't do what you're trying to do, and what's more, you really shouldn't. Whatever base_obj.obj1 is, base_obj.obj1.type will get the type attribute of that, because base_obj.obj1.type means (base_obj.ob1).type --- that is, it evaluates the obj1 attribute first. There is no way to make base_obj.obj1 return one thing, but have the base_obj.obj1 part of base_obj.obj1.type be something different. At the time the lookup of obj1 happens, you do not know whether another attribute lookup is going to take place later.

There are good reasons for this. It would be very confusing if these gave different results:

# 1
x = base_obj.obj1.type

# 2
tmp = base_obj.obj1
x = tmp.type

If you want to get the value attribute, get the value attribute. If you want to be able to use obj1 in various situations as if it were its value attribute, you may be able to achieve what you want by overloading various operations on obj1 (so that, e.g., base_obj.obj1 + 2 works).

Upvotes: 1

Related Questions