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

kri*_*iss 15 python pep8

在python PEP8结束时我正在阅读:

当布尔值为时True,我对该推荐没有问题,但在检查时听起来很奇怪False

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

    if greeting == False:
Run Code Online (Sandbox Code Playgroud)

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

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

顺便说一下,有谁知道为什么if greeting is True:被描述为更糟糕if greeting == True:?我们还应该明白那if greeting is False:也更糟if greeting == False:吗?

pax*_*blo 17

我相信你读错了.尽量不要把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)
Run Code Online (Sandbox Code Playgroud)

要么:

if (customerDead == False)
Run Code Online (Sandbox Code Playgroud)

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

if (isComplete == True) ...
if ((isComplete == True) == True) ...
if (((isComplete == True) == True) == True) ...
if ((((isComplete == True) == True) == True) == True)...
Run Code Online (Sandbox Code Playgroud)

  • 这个化妆品论证是有效的,但我认为它在某种程度上错过了这个问题.OP询问说'不是x`和'x是假'之间的*功能*区别.他似乎确实理解了差异,我想他想知道为什么前者的*行为*被推荐为后者. (4认同)

Gle*_*ard 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)
Run Code Online (Sandbox Code Playgroud)

if enabled == False会导致这不起作用.

False是一个错误值,但它不是唯一的错误值.避免使用相同的原因,避免与True和False进行比较isinstance.


Rya*_*eer 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
Run Code Online (Sandbox Code Playgroud)

is检查传递的值是否完全是 True/False,而不是它是否计算TrueFalse.

此行为允许:

if var is False:
   # False (bool) case
elif var is None:
   # None case
elif var == 0:
   # integer 0 case
Run Code Online (Sandbox Code Playgroud)

if var == False:
    # catches False & 0 case; but not None case, empty string case, etc.
Run Code Online (Sandbox Code Playgroud)

这似乎违反直觉 - 这就是为什么我期望PEP8说"不要这样做".

至于说这里使用is身份,而是使用==平等.

你只需要使用if var is True时您需要的布尔值True,但要拒绝1,'some string'等等.

这种情况对大多数读者来说可能并不明显; 我怀疑PEP8声称它可能具有误导性"更糟糕".它有时可能是必要的邪恶; 但是......如果你发现自己需要is True,它可能表明存在设计问题.在任何情况下,您都应该评论"为什么"您需要完全 True或者False如果您曾经使用过is.


Wal*_*ter 4

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

另一方面,foo == []or的语义值foo == False有时更有价值,因此应该使用(恕我直言)代替not foo。具体来说,这取决于您想要沟通的内容。事实上not foo 意味着foo一个假值?”,而foo == False 意味着foo与?具有相同的值False”。

PEP 声明其包含的所有内容均为指导方针。规则也有例外,这一次也不例外。

  • 我当然从来没有听过说英语的人说“如果今天去商店等于假” (4认同)
  • 我可以设计一个:具有类似 Pickle 行为的库,例如。腌制 `False` 与腌制 `""` 不同。 (3认同)
  • `foo == False` 几乎*不*应该被使用;我什至无法想象出一种正确的做法。 (2认同)