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



我对Python相对陌生,我发现自己必须评估函数/静态方法中的许多参数,我在想是否有一种用户友好的方法可以做到这一点,所以我最终写了一个这样的函数:

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函数只是增加了不必要的复杂性。如果需要类型检查,我只需要将其放入函数中,并将默认值声明为实际默认值:

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

您的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]"

如果小心使用泛型,可能会出现这种情况,但您需要将返回值分配给不同的名称,这只会使其更难使用。

我常用的取消Optional默认值-None参数的模式是:

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(或任何不可变类型(,您可以只做:

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

这就避免了整个问题!optional_arg or default技巧实际上只适用于默认值将发生变化并且需要为每个函数调用构造一个新对象的情况(例如,您希望将默认值初始化为一个新的空列表,以便可以向其添加项(。

最新更新