2

I have:

class C:
    aaa=2


class B:
     def __init__ (self,name):
         self.name
         self.value

How can i define class C so when i dynamically set attribute to instance it make that attribute instance of class B. And attribute name of class B have to have attribute name equal string of name of that new attribute in class C and attribute value of B instance have to have value what set in new attribute in instance of class C.

Have to give me that result:

>> c=C()
>> c.whatever= 'strinstrinsstring'
>> isinstance(c.whatever,B)
True
>> c.whatever.value
'strinstrinsstring'
>>c.whatever.name
'whatever'
3
  • 4
    I would like to encourage you to work on the clarity of your question.
    – NPE
    Commented Dec 15, 2010 at 17:29
  • Sorry, i even didn't know what world clarity mean. :) But I think you can get clarity from a code... :) But anyway tanks for pushing me to learn English )...
    – Pol
    Commented Dec 15, 2010 at 17:41
  • Why would you want that? Commented Dec 15, 2010 at 17:42

2 Answers 2

5

Just smartly override __setattr__. If you want to do it only for a specific attribute, then put in a special case for the attribute name that you want to look for:

>>> class B:
    def __init__(self, name, value):
        self.name = name
        self.value = value


>>> class C:
    def __setattr__(self, name, value):
        if name == 'makeMeB':
            newb = B(name, value)
            self.__dict__[name] = newb
        else:
            self.__dict__[name] = value

>>> c = C()
>>> c.makeMeB = 'foo'
>>> isinstance(c.makeMeB, B)
True
>>> c.makeMeB.name
'makeMeB'
>>> c.makeMeB.value
'foo'
>>> c.blah = 'foo'
>>> isinstance(c.blah, B)
False

If you want it for every attribute, just forget the if and it'll do it for everything:

>>> class B:
    def __init__(self, name, value):
        self.name = name
        self.value = value


>>> class C:
    def __setattr__(self, name, value):
        attr_as_b = B(name, value)
        self.__dict__[name] = attr_as_b

>>> c = C()
>>> c.makeMeB = 'foo'
>>> isinstance(c.makeMeB, B)
True
>>> c.makeMeB.name
'makeMeB'
>>> c.makeMeB.value
'foo'
>>> c.amIalsoB = 'well?'
>>> isinstance(c.amIalsoB, B)
True
>>> c.amIalsoB.name
'amIalsoB'
>>> c.amIalsoB.value
'well?'
7
  • I think this is the right idea, but the OP wants all dynamically set attributes of class C to be instances of class B, not just some with a special name. -- so no if name == 'makeMeB': required.
    – martineau
    Commented Dec 15, 2010 at 17:41
  • Yeah that wasn't clear from the question, so I went with the slightly more specific version that would be easier to scale back from. I'll edit the other one in as well. Commented Dec 15, 2010 at 17:42
  • 1
    But don’t use __dict__ directly, use super(C, self).__setattr__ instead (and then you would have to use new-style classes via subclassing object too, what I would recommend anyway). Otherwise this may break __setattr__ customizations of superclasses one may use.
    – nils
    Commented Dec 15, 2010 at 17:51
  • Yeah I didn't use the new-style classes because the OP didn't. As-is there's nothing to super. Good advice though, +1 Commented Dec 15, 2010 at 17:55
  • @Pol: OP means "original poster", the originator of a particular thread. Commented Dec 15, 2010 at 18:07
1

This is a horrible thing to do, because it changes what attributes mean!

Why not just look at the __dict__ of c:

>>> class C(object):
...     pass
...
>>> c = C()
>>> c.spam = 'ham'
>>> c.__dict__
{'spam': 'ham'}
2
  • Ah but you can :) See my answer! Commented Dec 15, 2010 at 17:32
  • @Daniel: oh, I see! I didn't parse the question properly. What a nasty thing to do :p
    – Katriel
    Commented Dec 15, 2010 at 17:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.