如何实现Python中类似any()和all()的one()函数?
实现Python风格的one()函数:判断可迭代对象中仅有一个真值
我在Python中常用any()和all()函数,但有时需要一个one()函数,用于判断列表(或其他可迭代对象)中是否仅有一个值在布尔上下文中为True。目前的实现用嵌套if语句,不仅写法繁琐,还只能适配两个元素的场景,实际需要支持任意数量元素。当前实现代码如下:
# 实际场景中元素数量可能不止两个 istrue = [True, False] isfalse = [True, 'foobar'] isfalse2 = [False, False] def one(values): if values[0] and values[1]: return False if not values[0] and not values[1]: return False return True one(istrue) # 返回True one(isfalse) # 返回False one(isfalse2) # 返回False
更Pythonic的实现方式
方法1:简洁的统计式实现
利用Python中布尔值可直接参与数值计算的特性(True等价于1,False等价于0),直接统计可迭代对象中真值的数量是否为1:
def one(values): return sum(map(bool, values)) == 1
测试用例验证:
istrue = [True, False] isfalse = [True, 'foobar'] # 非空字符串属于真值 isfalse2 = [False, False] multi_element_true = [0, '', None, True, 0.0] # 仅最后一个元素为真值 print(one(istrue)) # True print(one(isfalse)) # False print(one(isfalse2)) # False print(one(multi_element_true)) # True
方法2:高效的提前终止实现
如果处理的可迭代对象数据量很大,上述方法需要遍历所有元素才能统计总数。可以优化为找到第二个真值时直接返回False,减少不必要的遍历:
def one(values): true_count = 0 for val in values: if bool(val): true_count += 1 if true_count > 1: return False return true_count == 1
这个版本在遇到第二个真值时立刻终止循环,性能更优,同时支持所有可迭代对象类型(包括生成器这类惰性迭代的对象)。
内容的提问来源于stack exchange,提问作者buhtz
相关产品推荐
相关产品推荐

