在 Python 中,我应该如何测试一个变量是 None、True 还是 False
Posted
技术标签:
【中文标题】在 Python 中,我应该如何测试一个变量是 None、True 还是 False【英文标题】:In Python how should I test if a variable is None, True or False 【发布时间】:2011-01-02 11:57:38 【问题描述】:我有一个函数可以返回三件事之一:
成功 (True
)
失败 (False
)
错误读取/解析流 (None
)
我的问题是,如果我不应该针对 True
或 False
进行测试,我应该如何查看结果。以下是我目前的做法:
result = simulate(open("myfile"))
if result == None:
print "error parsing stream"
elif result == True: # shouldn't do this
print "result pass"
else:
print "result fail"
是否真的像删除== True
部分一样简单,或者我应该添加一个三布尔数据类型。我不希望simulate
函数抛出异常,因为我希望外部程序处理错误只是记录它并继续。
【问题讨论】:
你问错问题了;你应该寻求帮助来定义你的结果......你认为“失败”和“错误解析流”之间有什么区别,它们是什么意思,后果是什么,调用者可能想要采取什么行动在每种情况下(通过、失败、解析错误)? 我正在模拟一个电力系统,如果人们的房屋断电,那就是故障。如果我无法读取模拟文件,那就是完全不同的错误。 在simulate
函数中,我捕获了所有异常;我不希望模拟器内部发生任何事情来停止程序的其余部分运行(并处理下一个元素)。但答案让我改变了主意。
@James ***s:对。这就是 try/except 处理的全部内容。如果您的simulate
有它可以捕获并重试的东西,那很好。但如果它“失败”,它不应该返回None
。它应该只对调用它的脚本引发异常。无论哪种方式,simulate
都已完成。返回None
不如引发适当的异常有用——或者允许异常通过simulate
传播到调用脚本中进行处理。
@James,请改用except Exception:
。这会捕获所有“真实”错误,以及Warning
和StopIteration
。它允许KeyboardInterrupt
和SystemExit
通过。如果您真的想抓住这些,最好使用另一个外部 try/except 或其他一些清楚地记录您的意图的结构,因为这些不是“错误”。 (但我确实说过“几乎从不”......也许在你的情况下你真的想要抓住一切,甚至阻止 Ctrl-C 或 sys.exit()
退出等)
【参考方案1】:
if result is None:
print "error parsing stream"
elif result:
print "result pass"
else:
print "result fail"
保持简单明了。您当然可以预先定义字典。
messages = None: 'error', True: 'pass', False: 'fail'
print messages[result]
如果您打算修改 simulate
函数以包含更多返回代码,那么维护此代码可能会成为一个问题。
simulate
也可能会在解析错误时引发异常,在这种情况下,您要么在此处捕获它,要么让它向上传播一个级别,并且打印位将减少为单行 if-else声明。
【讨论】:
后者是一种针对真假的明确测试,不是吗? 当然可以,但是知道这些只是可能的返回值,我认为这不是问题。 而且好像也快了一点 a = 'foo' if a: print 'its true' a 实际上不是 TRUE,它不是没有 而不是假【参考方案2】:不要害怕例外!让您的程序只记录并继续很简单:
try:
result = simulate(open("myfile"))
except SimulationException as sim_exc:
print "error parsing stream", sim_exc
else:
if result:
print "result pass"
else:
print "result fail"
# execution continues from here, regardless of exception or not
现在,您可以从模拟方法获得更丰富的通知类型,以了解究竟出了什么问题,以防您发现错误/无错误信息不够丰富。
【讨论】:
同意。比上面明显更流行的解决方案(闻起来太像 C 代码)更具 Python 风格。 @Brandon 不同意。这段代码比上面的解决方案(或下面的改进版本)更长,更糟糕的是,可读性更低:更多的缩进,更多不同的语句 - 猜猜为什么后者更受欢迎,正如你所说的...... ;-) 为什么要'Pythonic' 如果这会导致更尴尬的代码......? 现在打印回溯而不是“错误解析流”,你得到了我的投票。 好吧,你还是得到了我的投票,但我的意思是打印类似traceback.format_exc()
的内容。 See this SO answer.
很多人会来到这个页面寻找标题问题的答案。对于我们大多数人来说,“不要害怕例外!”与我们的情况无关。我们只需要测试 True、False 和 None。虽然您建议的替代方案在某些情况下有效,但我认为最好也包括对问题的回答。【参考方案3】:
从不,从不,从不说
if something == True:
从来没有。这太疯狂了,因为您在重复重复被冗余指定为 if 语句的冗余条件规则的内容。
更糟糕的是,仍然,从不,从不,从不说
if something == False:
你有not
。随意使用。
最后,a == None
效率低下。做a is None
。 None
是一个特殊的单例对象,只能有一个。只需检查您是否拥有该对象。
【讨论】:
用True
测试是否相等并不是多余的(尽管我同意这不明智)。它可以调用__eq__
或其他特殊方法,它几乎可以做任何事情。
@Scott Griffiths:好点子。这是一个真实而深刻的可怕场景。如果情况确实如此,那么该程序违反了我们的基本期望,以至于它需要被简单地删除并从头开始重写,而无需使用这种黑魔法。
'从不,从不,从不' ...?在某些情况下,if something == True
产生的结果与if something
不同,例如对于非布尔值something
。 2==True
产生 false 而 2
计算结果为 true; None==False
是假的,但 not None
是真的!
-1 这个答案具有误导性并且完全不正确,因为@Rolf Bartstra 说的是真的。虽然在这种情况下,你所说的可以应用。
-1。因为something
的任何非零、非空或非零长度值都会在bool(something)
上返回True
。在这种情况下,如果您只想检查something
的值是否为True
,即bool
。然后你必须做if something == True
IMO。【参考方案4】:
有很多好的答案。我想再补充一点。如果您使用数值,那么您的代码可能会出现错误,而您的答案恰好是 0。
a = 0
b = 10
c = None
### Common approach that can cause a problem
if not a:
print(f"Answer is not found. Answer is str(a).")
else:
print(f"Answer is: str(a).")
if not b:
print(f"Answer is not found. Answer is str(b).")
else:
print(f"Answer is: str(b)")
if not c:
print(f"Answer is not found. Answer is str(c).")
else:
print(f"Answer is: str(c).")
Answer is not found. Answer is 0.
Answer is: 10.
Answer is not found. Answer is None.
### Safer approach
if a is None:
print(f"Answer is not found. Answer is str(a).")
else:
print(f"Answer is: str(a).")
if b is None:
print(f"Answer is not found. Answer is str(b).")
else:
print(f"Answer is: str(b).")
if c is None:
print(f"Answer is not found. Answer is str(c).")
else:
print(f"Answer is: str(c).")
Answer is: 0.
Answer is: 10.
Answer is not found. Answer is None.
【讨论】:
【参考方案5】:我想强调一点,即使在某些情况下 if expr :
还不够,因为人们想确保 expr
是 True
而不仅仅是与 0
/None
/whatever 不同, is
优先于 ==
for the same reason S.Lott mentionned for avoiding == None
。
它确实稍微更有效,而且,蛋糕上的樱桃,更易于阅读。
In [1]: %timeit (1 == 1) == True
38.1 ns ± 0.116 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [2]: %timeit (1 == 1) is True
33.7 ns ± 0.141 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
【讨论】:
你不能运行一次基准测试并说一个比另一个更有效(即使它可能是)。运行多次 (10.000) 以查看它的平均表现。\【参考方案6】:我相信对于您的情况来说,抛出异常是一个更好的主意。另一种方法是返回元组的模拟方法。第一项是状态,第二项是结果:
result = simulate(open("myfile"))
if not result[0]:
print "error parsing stream"
else:
ret= result[1]
【讨论】:
返回元组通常与解包元组很相配;) 但是,您的代码没有多大意义,如果返回False
,它将打印'error parsing stream'
。
模拟方法应返回 (False, "anything at all") 或 (True, ret),其中 ret 为 False 或 True。
好吧,您正在重新定义输出值以适合您的逻辑,不清楚没有解释以上是关于在 Python 中,我应该如何测试一个变量是 None、True 还是 False的主要内容,如果未能解决你的问题,请参考以下文章