验证函数三个参数是否为数字:现有代码是否可行?有无更优方案?
参数类型校验的疑问解答
问题描述
我编写了一个接收3个参数的函数,希望确保这三个参数均为数字。目前我通过试验写出了如下代码,看似可行,但因不了解布尔运算符的优先级,无法确定其正确性:
assert type(x)==type(y)==type(z) in (int, float), "Please provide numbers"
我想确认:
- 这段代码是否有效?
- 是否存在更优的实现方式?(我是新手,可能遗漏了常见方法)
1. 这段代码是否有效?
这段代码能运行但存在明显漏洞:
- Python的比较运算符是链式结合的,
type(x)==type(y)==type(z) in (int, float)等价于(type(x)==type(y)) and (type(y)==type(z)) and (type(z) in (int, float)),逻辑上要求三个参数类型完全相同,且该类型是int或float。 - 但它会错误排除很多合法数字:比如
bool类型(True/False是int的子类,type(True)为bool,不在(int, float)范围内)、自定义数字子类、numpy数值类型等。 - 同时写法可读性差,其他人阅读时需要额外梳理链式比较的逻辑,容易产生误解。
2. 更优的实现方式
方式一:使用isinstance()(最推荐)
isinstance()会考虑继承关系,能正确识别所有数字子类,写法清晰直观:
assert all(isinstance(arg, (int, float)) for arg in (x, y, z)), "Please provide numbers"
- 优点:允许三个参数类型不同(比如一个
int、一个float),只要都是数字类型即可;天然支持bool类型(如果不需要bool,补充判断即可)。 - 排除
bool的版本:
assert all(isinstance(arg, (int, float)) and not isinstance(arg, bool) for arg in (x, y, z)), "Please provide numbers"
方式二:利用数字运算特性(兼容更多扩展数字类型)
如果需要支持Decimal、numpy数值这类非原生数字类型,可以通过“尝试运算+捕获异常”的方式:
try: # 执行只有数字能完成的简单运算,比如加0 _ = x + 0 _ = y + 0 _ = z + 0 except TypeError: raise ValueError("Please provide numbers")
- 优点:兼容所有实现了数字运算的类型;缺点:如果参数是其他可相加的非数字类型(比如字符串),会出现误判。
方式三:保留“类型完全相同”的需求(若确实需要)
如果你明确要求三个参数类型必须完全一致,可以把代码写得更直白,避免链式比较的歧义:
target_type = type(x) assert target_type in (int, float) and type(y) == target_type and type(z) == target_type, "Please provide numbers"
内容的提问来源于stack exchange,提问作者Chargou
相关产品推荐
相关产品推荐

