setattr for secondary attribute

Bengt Richter bokr at oz.net
Mon Nov 21 18:32:44 EST 2005


On 20 Nov 2005 20:34:39 -0800, "Alex" <OurLab at gmail.com> wrote:

>I apologize for asking  maybe a very trivial question.
>I have a new class object A with slots. One of the slots is, for
>example, object spam. Object spam, in turn, also has slots and one of
>them is attribute eggs. I need to assign a new value to eggs. In other
>words, I need to perform the following:
>
>A.spam.eggs=newValue
>
>The problem is that I have only a string s='spam.eggs' with which to
>work, so I cannot write an expression written above. I tried to use
>setattr:
>
>setattr(A, s, newValue)
>
>but this does not work. It says that object A does not have attribute
>spam.eggs
>
>How would you do it? TIA.
>
    A.spam.eggs=newValue

(which would work) really means, if you break it into steps

    (A.spam).eggs = newValue

which is

    setattr(getattr(A, 'spam'), 'eggs', newValue)

so you just need to break 'spam.eggs' apart and plug in the pieces.
assuming exactly one dot and no spaces to worry about,

    s_spam, s_eggs = s.split('.')

then

    setattr(getattr(A, s_spam), s_eggs, newValue)

ought to do the job.

If you have more than one dot, e.g., s = 'spam.eggs.ham'
and eggs has a slot ham that you want to assign to, then you need to
loop on getattr for all but the last name, which you use for the setattr.
Something like (untested)

    def setbydots(A, s, val):
        names = s.split('.')
        for name in names[:-1]:
            A = getattr(A, name)
        setattr(A, names[-1], val)

This should work for no dots or any number, so long as the reference chain is valid.
E.g.,
    setbydots(A, 'spam.eggs', newValue)
should accomplish
    A.spam.eggs=newValue
as you wanted. I hope ;-)

( posting delayed >12 hrs due to news server prob ;-/ )

Regards,
Bengt Richter



More information about the Python-list mailing list