def get_attr(obj: Any, key: str, inner_key: str = None) -> Any:
    """
    Alias for python `getattr` method. Useful for Callbacks preparation
    and cases with multi-criterion, multi-optimizer setup.
    For example, when you would like to train multi-task classification.

    Used to get a named attribute from a `IRunner` by `key` keyword;
    for example\
    ::

        get_attr(runner, "criterion")
        # is equivalent to
        runner.criterion

        get_attr(runner, "optimizer")
        # is equivalent to
        runner.optimizer

        get_attr(runner, "scheduler")
        # is equivalent to
        runner.scheduler

    With `inner_key` usage, it suppose to find a dictionary under `key`\
    and would get `inner_key` from this dict; for example,
    ::

        get_attr(runner, "criterion", "bce")
        # is equivalent to
        runner.criterion["bce"]

        get_attr(runner, "optimizer", "adam")
        # is equivalent to
        runner.optimizer["adam"]

        get_attr(runner, "scheduler", "adam")
        # is equivalent to
        runner.scheduler["adam"]

    Args:
        obj: object of interest
        key: name for attribute of interest,
            like `criterion`, `optimizer`, `scheduler`
        inner_key: name of inner dictionary key

    Returns:
        inner attribute
    """
    if inner_key is None:
        return getattr(obj, key)
    else:
        return getattr(obj, key)[inner_key]

    Alias for python `getattr` method. Useful for Callbacks preparation
    and cases with multi-criterion, multi-optimizer setup.
    For example, when you would like to train multi-task classification.

    Used to get a named attribute from a `IRunner` by `key` keyword;
    for example    ::

        get_attr(runner, "criterion")
        # is equivalent to
        runner.criterion

        get_attr(runner, "optimizer")
        # is equivalent to
        runner.optimizer

        get_attr(runner, "scheduler")
        # is equivalent to
        runner.scheduler

    With `inner_key` usage, it suppose to find a dictionary under `key`    and would get `inner_key` from this dict; for example,
    ::

        get_attr(runner, "criterion", "bce")
        # is equivalent to
        runner.criterion["bce"]

        get_attr(runner, "optimizer", "adam")
        # is equivalent to
        runner.optimizer["adam"]

        get_attr(runner, "scheduler", "adam")
        # is equivalent to
        runner.scheduler["adam"]

    Args:
        obj: object of interest
        key: name for attribute of interest,
            like `criterion`, `optimizer`, `scheduler`
        inner_key: name of inner dictionary key

    Returns:
        inner attribute
    
catalyst/utils/misc.py