5

I know I can get a Class's attributes with a string like this:

object.attribute = 'foo'
x = 'attribute'
getattr(object, x)
>>> 'foo'

Is there a way to "go deeper" into the object's attributes with a string? In other words, if my object contains another object, how can I get the the sub-object's attributes with a string? For example:

object.object.attribute

3 Answers 3

14

The operator.attrgetter function does this:

class Foo: pass
f = Foo()
f.bar = Foo()
f.bar.baz = Foo()
f.bar.baz.quux = "Found me!"

import operator
print operator.attrgetter("bar.baz.quux")(f)     # prints "Found me!"
Sign up to request clarification or add additional context in comments.

3 Comments

HA! I forgot the attrgetter follows dot notation
Even better, but thanks anyway @jdi.. I learned more about lambdas from your answer.
@MFB: No worries. Ned's answer is better since its a stdlib version of the same thing that is also faster.
6

I love the recipe given in this link (actually the comment is even better though)

Example borrowed from Claudiu's answer (which is great too):

class Foo: pass
f = Foo()
f.bar = Foo()
f.bar.baz = Foo()
f.bar.baz.quux = "Found me!"

A recursive getattr that follows dots:

>>> rgetattr = lambda o,a: reduce(getattr, a.split('.'), o)
>>> rgetattr(f, 'bar.baz.quux')
'Found me!'

The non-lambda version being:

def rgetattr(obj, attr):
    return reduce(getattr, attr.split('.'), obj)

2 Comments

Oh booyah. Thanks to @Claudiu too
ah i haven't been doing enough functional programming lately. totally didn't see this as a reduce, but it obviously is
4
>>> class Foo: pass

>>> f = Foo()
>>> f.bar = Foo()
>>> f.bar.baz = Foo()
>>> f.bar.baz.quux = "Found me!"
>>> getattr(f, 'bar')
<__main__.Foo instance at 0x01EC5918>
>>> getattr(getattr(f, 'bar'), 'baz')
<__main__.Foo instance at 0x01EC5A30>
>>> getattr(getattr(getattr(f, 'bar'), 'baz'), 'quux')
'Found me!'

EDIT: Done as a simple method:

>>> def dynamic_lookup(obj, dot_attrs):
    attr_list = dot_attrs.split(".")
    while attr_list:
        obj = getattr(obj, attr_list.pop(0))
    return obj

>>> f
<__main__.Foo instance at 0x01EC50A8>
>>> dynamic_lookup(f, 'bar.baz.quux')
'Found me!'

Easily adaptable to take a list of strings (take attr_list directly instead of dot_attrs), but I thought the . notation as a string would look cooler...

2 Comments

Ah yes, but what about object.object.object.attribute? j/k :-)
That's cool. How could I build the final method from a list of strings?

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.