奇怪的PEP8建议将布尔值与True或False进行比较

时间:2010-10-29 08:47:31

标签: python pep8

在python结尾PEP8我正在读:

  • 请勿使用==

    将布尔值与True或False进行比较
    Yes:   if greeting:
    No:    if greeting == True:
    Worse: if greeting is True:
    

当布尔值为True时,我对该建议没有任何问题,但在检查False

时听起来很奇怪

如果我想知道变量问候语是否为假,我为什么不写:

    if greeting == False:

如果我写if not greeting:,它将具有与上述陈述截然不同的含义。如果问候语是什么怎么办?如果是空字符串怎么办?这个PEP8推荐是否意味着存储布尔值的变量应该只包含True或False,并且这些变量应该避免None?

在我看来,它似乎是来自其他语言的静态类型的推荐,并且不适合python,至少与False比较。

顺便说一句,是否有人知道为什么if greeting is True:被描述为if greeting == True:更糟?我们是否还应该理解if greeting is False:也比if greeting == False:更糟糕?

6 个答案:

答案 0 :(得分:16)

我相信你读错了。尽量不要将greeting视为名词而不是动词(“我在问候”而不是“这是问候语”)。

您可以在PEP8的序言中看到线索:

  

Guido的一个重要见解是,代码的读取频率远高于编写代码。此处提供的准则旨在提高代码的可读性。

为此,代码应尽可能类似于书面或口头的单词。你现实生活中没有说"If I am annoying you is true, let me know",你只需说"If I am annoying you, let me know"

这就是为什么你倾向于看到像isOpenhasBeenProcessed这样的布尔变量的原因之一,因为它们有助于代码的可读性。

你永远不应该做类似的事情:

if (isOpen == True)

或:

if (customerDead == False)

只是因为你已经在变量名中有一个布尔值。所有相等都给你另一个布尔值,并调用reduction ad absurdum,你会在哪里停止?

if (isComplete == True) ...
if ((isComplete == True) == True) ...
if (((isComplete == True) == True) == True) ...
if ((((isComplete == True) == True) == True) == True)...

答案 1 :(得分:5)

这是鸭子打字的一部分。在Python中,您通常不希望将您接受的内容限制为特定类,而是限制公开适当API的对象。例如,我可以这样做:

class MyProperty(object):
    """
    A file-backed boolean property.
    """
    def __init__(self, filename):
        self.value = open(filename).read()
    def __nonzero__(self):
        return self.value != "0"
    def save_to_disk(self):
        # ... and so on
        pass

def func(enabled):
    if not enabled:
        return
    # ...

enable_feature = MyProperty("enable_feature")
func(enable_feature)

if enabled == False会导致此操作失效。

False是 a false值,但它不是唯一的 false值。出于避免使用isinstance的原因,请避免与True和False进行比较。

答案 2 :(得分:5)

通过==!=比较不比较真相的最简单的理由似乎是:

0 is False # Result: False
0 == False # Result: True; 0 evaluates comparatively to False

1 is True  # Result: False  
1 == True  # Result: True; 1 evaluates comparatively to True

is检查传递的值是否完全 True / False,而不是评估True }或False

此行为允许:

if var is False:
   # False (bool) case
elif var is None:
   # None case
elif var == 0:
   # integer 0 case

,而

if var == False:
    # catches False & 0 case; but not None case, empty string case, etc.

这似乎是违反直觉的 - 这就是为什么我希望PEP8表示不会这样做"。

如上所述here使用is表示身份,但使用==表示相等

您只需要在需要bool值if var is True时使用True,但又想拒绝1'some string'等。

这种情况对大多数读者来说可能并不明显;我怀疑PEP8声称它更糟糕"更糟糕"因为可能会误导。它有时可能是必要的邪恶;但是......如果您发现自己需要is True可能表示设计问题。无论如何,你应该评论"为什么"如果您使用True,则需要完全 Falseis

答案 3 :(得分:1)

我理解它的方式PEP的建议意味着,如果你知道可以合理地确定foo的类型(通常是这种情况),那么测试显式错误值是多余的并且降低了可读性。例如,在foo = [i for i in range(10) if i == x]中,您可以非常确定唯一的错误值foo可以是[](假设没有引发异常)。在这种情况下,使用foo == []是多余的,not foo更好。

另一方面,foo == []foo == False的语义值有时更有价值,然后使用(恕我直言)而不是not foo。具体取决于您尝试沟通的内容。事实上,not foo 表示foo a 错误值?”,而foo == False 表示foo与[{1}}具有相同的价值?“。

PEP声明它包含的所有内容都是指南。规则有例外,这个也不例外。

答案 4 :(得分:1)

我不确定其他评论是否回答了您的问题。你说:

  

如果我写if not greeting:,它将与上面的陈述有很大不同。 如果问候语为“无”怎么办?如果它是空字符串怎么办?

实际上,not greetinggreeting == False具有不同的含义。但是PEP8并不是说相反的意思,也不是说不使用greeting == False。它说:

  

请勿使用==

布尔值的值与True或False进行比较

None和空字符串都不是布尔值。因此,请适当使用greeting == False,而greeting可以是非布尔值。


有人在您的问题下方发表了评论:

  

...为什么有时有时是None,有时是布尔,有时是str?那只是在问各种各样的麻烦。

不是。这是一个用例:您有一个患者数据库,其中有一个字段说明患者是否死于自杀。假设我们有Patient类,属性为suicidesuicide将具有三个可能的值:

  • True的意思是“是的,我们知道他自杀了”
  • False的意思是“不,我们知道他死于其他东西”
  • None的意思是“我们实际上并不知道”。

然后,如果您想研究未死于自杀的患者,则可以执行以下操作:

# load database
...

# filter patients
database = [patient for patient in database if patient.suicide == False]  # if greeting == False:

# study database
...

QED。这是数据科学中的典型案例。值False表示您知道某些错误,而值None表示您什么都不知道。

答案 5 :(得分:0)

我通常在模式IsName之后命名我的布尔变量,所以在你的情况IsGreeting。这使支票读取if IsGreeting / if not IsGreeting,这非常直观。

您使用if not描述的歧义是在布尔比较中使用非布尔类型的结果。这通常应该避免,因为它非常混乱。