Recursive ``getattar``.

    This can be used as a drop in for the standard ``getattr(...)``. Credit to:
    https://stackoverflow.com/a/31174427

    Args:
        obj: Object to retrieve the attribute from.
        attr: Name of the attribute, with each successive attribute separated by a ".".
    Returns:
        The requested attribute. (Same as ``getattr``).
    Raises:
        AttributeError: If the attribute was not found and no default was provided. (Same as ``getattr``).

def recursive_getattr(obj: Any, attr: str, *args) -> Any:
    """ Recursive ``getattar``.

    This can be used as a drop in for the standard ``getattr(...)``. Credit to:
    https://stackoverflow.com/a/31174427

    Args:
        obj: Object to retrieve the attribute from.
        attr: Name of the attribute, with each successive attribute separated by a ".".
    Returns:
        The requested attribute. (Same as ``getattr``).
    Raises:
        AttributeError: If the attribute was not found and no default was provided. (Same as ``getattr``).
    """
    def _getattr(obj, attr):
        return getattr(obj, attr, *args)
    return functools.reduce(_getattr, [obj] + attr.split('.'))