1

Suppose I have two Python classes, A and B. I would like to be able to do the following:

>>> b = B()
>>> b.a.attr1 = 'foo'
>>> b.a.attr2 = 'bar'

where 'a' is an instance of A. I can't use __setattr__ as I would if 'a' was some "primitive" type. Is there some elegant way to accomplish this, other than

>>> b = B()
>>> b.a = A()
>>> b.a.attr1 = 'foo'
>>> b.a.attr2 = 'bar'

?

2
  • 6
    Why not to put self.a = A() into B.__init__ method? Commented Nov 21, 2012 at 9:19
  • I should have mentioned... I can't do that because many of the classes I would unconditionally instantiate in __init__ (potentially) won't be used. Also, some code in A() may fire at __init__ time that I won't necessarily be ready for. Thanks. Commented Nov 21, 2012 at 9:53

2 Answers 2

2

You'd have to either create a in the __init__ of B, use a __getattr__ hook to create a dynamically, or use a property.

__init__ approach:

class B(object):
    def __init__(self):
        self.a = A()

__getattr__ approach:

class B(object):
    def __getattr__(self, attr):
        if attr == 'a':
            self.a = A()
            return self.a
        raise AttributeError(attr)

Property approach:

class B(object):
    _a = None

    @property
    def a(self):
        if self._a is None:
            self._a = A()
        return self._a

Of course, the property and __getattr__ approaches do not have to store the A() instance on self, it could just return a pre-existing A() instance from somewhere else instead.

Sign up to request clarification or add additional context in comments.

1 Comment

HA!! Your __getattr__ approach does exactly what I'm looking for. I wouldn't have thought to use __GETattr__, as I'm setting an attribute with b.a.attr1='foo' __init__ is not an option for me because I don't want to instantiate a bunch of classes that I won't potentially be using. I should have mentioned that. Thanks.
0
class A(object):
    pass

class B(object):
    def __init__(self):
        self.a = A()

b = B()
b.a.attr1 = 'foo'
b.a.attr2 = 'bar'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.