from functools import reduce


def deepgetattr(obj, attr, default=None, raise_if_missing=False):
    """Recurses through an attribute chain to get the ultimate value."""
    if isinstance(attr, str):
        attr = attr.split('.')
    try:
        return reduce(getattr, attr, obj)
    except AttributeError:
        if raise_if_missing:
            raise
        return default