Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested objects and setattr & getattr (yes, it's that time)

Tags:

python

Overview:

class Inner(object):
    def __init__(self, x):
        self.x = x

class Outer(object):
    def __init__(self, z):
        self.inner = Inner(z)

o = Outer(10)

Now, I want the Outer object to behave transparently -- any attributes set on o should be set on o.inner, same for reading: o.something should return, in fact, the value of o.inner.sommething. Kind of like a proxy or a relay.

__getattr__ for Outer seems simple & works:

def __getattr__(self, item):
    return getattr(self, item)

How would I handle __setattr__? I couldn't come up with anything that didn't cause a recursion error and make me hate myself.

Or is the concept itself flawed?

(Another approach I tried was making Outer a subclass of Inner -- this didn't really play aesthetically the present@classmethods, not to mention the IDE would get lost inside those - not able to resolve some attributes. Let's leave that for now, perhaps?)

like image 383
ntl0ve Avatar asked Feb 07 '12 17:02

ntl0ve


People also ask

What is Setattr?

The setattr() function sets the value of the specified attribute of the specified object.

What is Setattr () and Getattr () used for?

What is getattr() used for in Python? We use the Python setattr() function to assign a value to an object's attribute. There might arise a situation where we might want to fetch the values assigned to the attributes. To provide this functionality, Python getattr() built-in function is used.

Why we use Setattr in Python?

Python setattr() function is used to set a value to the object's attribute. It takes three arguments an object, a string, and an arbitrary value, and returns none. It is helpful when we want to add a new attribute to an object and set a value to it.

What will happen if the attribute is not found in Setattr () method?

Return Value: None. The following example sets values for various attributes of an object. If the specified attribute does not exist in the class, the setattr() creates a new attribute to an object or class and assigns the specified value to it. The following assigns a new attribute to the class itself.


1 Answers

The tricky part is setting the inner attribute of the Outer class correctly. What you can do is call the __setattribute__ method of object (base class of Outer):

class Inner(object):
    def __init__(self, x):
        self.x = x

class Outer(object):    
    def __init__(self, z):
        object.__setattr__(self, 'inner', Inner(z))

    def __getattr__(self, name):
        return getattr(self.inner, name)

    def __setattr__(self, name, value):
        return setattr(self.inner, name, value)

Now, it works correctly:

o = Outer(10)
print o.x        # 10
print o.inner.x  # 10
o.g = 3
print o.g        # 3
print o.inner.g  # 3

However, it's not clear to my why you don't want to use inheritance in this case. It seems more natural and pythonic to have Outer inherit from Inner.

like image 200
jterrace Avatar answered Oct 31 '22 18:10

jterrace