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
Download
Copy to clipboard
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
callablething 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 toTypeErrors 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,