在 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)

我的问题是,如果我不应该针对 TrueFalse 进行测试,我应该如何查看结果。以下是我目前的做法:

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:。这会捕获所有“真实”错误,以及WarningStopIteration。它允许KeyboardInterruptSystemExit 通过。如果您真的想抓住这些,最好使用另一个外部 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 NoneNone 是一个特殊的单例对象,只能有一个。只需检查您是否拥有该对象。

【讨论】:

True 测试是否相等并不是多余的(尽管我同意这不明智)。它可以调用__eq__ 或其他特殊方法,它几乎可以做任何事情。 @Scott Griffiths:好点子。这是一个真实而深刻的可怕场景。如果情况确实如此,那么该程序违反了我们的基本期望,以至于它需要被简单地删除并从头开始重写,而无需使用这种黑魔法。 '从不,从不,从不' ...?在某些情况下,if something == True 产生的结果与if something 不同,例如对于非布尔值something2==True 产生 false 而 2 计算结果为 true; None==False 是假的,但 not None 是真的! -1 这个答案具有误导性并且完全不正确,因为@Rolf Bartstra 说的是真的。虽然在这种情况下,你所说的可以应用。 -1。因为something 的任何非零、非空或非零长度值都会在bool(something) 上返回True。在这种情况下,如果您只想检查something 的值是否为True,即bool。然后你必须做if something == TrueIMO。【参考方案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 : 还不够,因为人们想确保 exprTrue 而不仅仅是与 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的主要内容,如果未能解决你的问题,请参考以下文章

我如何测试一个 Python 变量是一个集合 [重复]

如何在python中测试变量是不是为空[重复]

自动化测试时需要使用python,请问如何理解python中的全局变量和局部变量?

如何比较python中的变量类型? [复制]

如何在 python 中“测试”NoneType?

如何检查python中变量的分布? [关闭]