getattr
allows one to obtain an attribute from an object given it's name as a string. multi_getattr
does the same thing but with dotted strings that can represent nested attributes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | def multi_getattr(obj, attr, default = None):
"""
Get a named attribute from an object; multi_getattr(x, 'a.b.c.d') is
equivalent to x.a.b.c.d. When a default argument is given, it is
returned when any attribute in the chain doesn't exist; without
it, an exception is raised when a missing attribute is encountered.
"""
attributes = attr.split(".")
for i in attributes:
try:
obj = getattr(obj, i)
except AttributeError:
if default:
return default
else:
raise
return obj
# Example usage
obj = [1,2,3]
attr = "append.__doc__.capitalize.__doc__"
multi_getattr(obj, attr) #Will return the docstring for the
#capitalize method of the builtin string
#object
|
This first became useful to me when I needed to make some alterations to http://djangosnippets.org/snippets/660/. It seemed useful enough to generalise a little.
Tags: attributes, getattr
Thank you, I would suggest two improvements: a) allow callables b) allow default values which have a truth value of False (e.g. None, 0, won't work with the recipe). Untested:
P.S.: a) If you had existing code doing
you could go with args instead (or in addition to) *kw
b) Also nice as a mixin class! :-)
Thanks Danny. I'm not sure about the
callable
thing though. It just seems like one of the many things that a given attribute could be "*able". Also, calling something just because it's callable might lead toTypeError
s in case of invalid number of arguments. I'd leave the calling to the user rather than to the function. The point about the defaults is very valid though. Thanks!I'm not sure I understand your second comment about the mixin classes. Can you elaborate?
Great recipe. :)
Note that operator.attrgetter supports this out of the box in Python 2.6 and later.
Ah. Thanks Stefan. I needed this for a 2.5 python and that too inside a Django template tag where the environment is quite limited.
hi N -
The recipe is rather simple, but really pythonic and practical, i liked it.
But when I reproduced this one in my own project, I changed the function name to get_nested_attr.
Thanks,