Very old question but it really needs a good answer. For even a short program, I'd say use a custom function!
Here's an example. It's not perfect for all application but it is for mine, for parsing responses from countless APIs and using Django. It's easy to fix for everyone's own requirements.
from django.core.exceptions import ObjectDoesNotExist
from functools import reduce
class MultipleObjectsReturned(Exception):
pass
def get_attr(obj, attr, default, asString=False, silent=True):
"""
Gets any attribute of obj.
Recursively get attributes by separating attribute names with the .-character.
Calls the last attribute if it's a function.
Usage: get_attr(obj, 'x.y.z', None)
"""
try:
attr = reduce(getattr, attr.split("."), obj)
if hasattr(attr, '__call__'):
attr = attr()
if attr is None:
return default
if isinstance(attr, list):
if len(attr) > 1:
logger.debug("Found multiple attributes: " + str(attr))
raise MultipleObjectsReturned("Expected a single attribute")
else:
return str(attr[0]) if asString else attr[0]
else:
return str(attr) if asString else attr
except AttributeError:
if not silent:
raise
return default
except ObjectDoesNotExist:
if not silent:
raise
return default