在 Python 中简洁地评估默认参数的最佳方法?

Best way to succinctly evaluate default parameters in Python?

相对较新 Python,我发现自己必须在 functions/static 方法中评估很多参数,我在想是否有一种用户友好的方法来做到这一点,所以我结束了写一个像这样的函数:

from typing import Any, Optional, Union

# Standard evaluator for default values
def eval_default(x: Any, default: Any, type: Optional[Any] = None) -> Any:
    """Helper function to set default value if None and basic type checking

    Args:
        x: the value to be evaluated
        default: the value to return if x is None
        type: the expected type of x, one of bool, int, float, str

    Raises:
        TypeError: for bool, int, float, str if x is not None and not of type

    Returns:
        x: either 'as is' if not None, or default if None, unless exception is raised.
    """
    # Infer type from default
    type = type(default) if type is None else type

    # Return default value if x is None, else check type and/or return x
    if x is None:
        return default
    elif not isinstance(x, type):
        if type == bool:
            raise TypeError("Variable can be either True or False.")
        elif type == int:
            raise TypeError("Variable must be an integer.")
        elif type == float:
            raise TypeError("Variable must be a float.")
        elif type == str:
            raise TypeError("Variable must be a string.")
    else:
        return x

然后在我的主要代码中我可以做类似的事情:


def some_method(self, some_variable:Optional[bool] = None) -> bool:
    """Some description
    """

    try:
        some_variable = eval_default(some_variable, False, bool)
    except TypeError:
        print("some_variable must be True or False.")

    return some_variable

是否有更简单、更简洁或更优雅的标准做法来处理这种情况?

非常感谢。

您的 eval_default 没有做任何事情来将类型从 Optional[bool] 缩小到 bool:

def some_method(self, some_variable:Optional[bool] = None) -> bool:
    try:
        some_variable = eval_default(some_variable, False, bool)
    except TypeError:
        print("some_variable must be True or False.")

    reveal_type(some_variable)  # note: Revealed type is "Union[builtins.bool, None]"

它可能会小心使用泛型,但您需要将 return 值分配给不同的名称,这只会使其更难使用。

我通常的 de-Optional-ing default-None args 模式是:

def some_method(self, some_variable:Optional[bool] = None) -> bool:
    some_variable = some_variable or False
    reveal_type(some_variable)  # note: Revealed type is "builtins.bool"

当然对于 bool(或 any 不可变类型)你可以这样做:

def some_method(self, some_variable: bool = False) -> bool:
    reveal_type(some_variable)  # note: Revealed type is "builtins.bool"

这就避免了整个问题! optional_arg or default 技巧实际上只适用于默认值是你要改变的东西并且你需要为每个函数调用构造一个新对象的情况(例如你想将默认值初始化为一个新的空列表所以你可以向其附加项目)。

在我看来,您的 eval_default 函数只是增加了不必要的复杂性。如果需要类型检查,我只是把它放在函数中,并将默认值声明为实际默认值:

def some_method(self, some_variable:Optional[bool] = False) -> bool:
    """Some description
    """

    if not isinstance(some_variable, bool):
        print(f"some_variable must be True of False")

    return some_variable

或者如果你需要一个可变的默认值:

def some_method(self, some_variable:Optional[list] = None) -> bool:
    """Some description
    """
    if some_variable is None:
        some_variable = []

    if not isinstance(some_variable, list):
        print(f"some_variable must be a list")

    return some_variable