def get_protected_attr_values(attr, df, privileged_group, privileged=True):
    """Retrieves all values given the privileged_group argument.

    If privileged is True and privileged_group[attr] is a list then it returns
    the list, if it's a function then values of df[attr] for which the function
    returns True. 

    If privileged is False and privileged_group[attr] is a list then it returns
    values of df[attr] not in the list else if it's a function returns values 
    of df[attr] for which the function returns False. 

    Parameters
    ----------
    attr: str
        Protected attribute which is a key of the privileged_group
        dictionnary
    df: pd.DataFrame
        Dataframe to extract privilieged group from.
    privileged_group: dict
        Dictionnary with protected attribute as key (e.g. age or gender)
        and a list of favorable value (like ['Male']) or a function
        returning a boolean corresponding to a privileged group
    privileged: bool (default True)
        Boolean prescribing whether to
        condition this metric on the `privileged_groups`, if `True`, or
        the `unprivileged_groups`, if `False`.

    Returns
    -------
    list:
        List of privileged values of the protected attribyte attr 
        if privileged is True else unprivileged values

    Raises
    ------
    ValueError:
        attr must be in privileged_group
    """
    if attr not in privileged_group:
        raise ValueError('attr must be in privileged_group')

    val = privileged_group[attr]
    if type(val) == list:
        if privileged:
            return val

        def fn(x): return x in val
    else:
        fn = val

    cond = df[attr].apply(fn) == privileged
    return df[cond][attr].unique().astype(str).tolist()