python布尔值的作用_关于python:比较布尔值与True或False的奇怪PEP8建议

本文探讨了Python PEP8规范中关于比较布尔值与True或False的建议。作者提出疑问,为何不直接使用`if greeting == False:`来检查变量是否为False。讨论中指出,`if not greeting:`和`if greeting == False:`在语义上有区别,且在处理可能为None或空字符串的情况时会有不同结果。同时,建议使用`if greeting is None:`来处理None情况。文章还引发了关于使用`is`和`==`进行比较的讨论,以及在何时使用布尔变量以提高代码可读性的思考。

在python PEP8的末尾,我正在阅读:

不要使用==将布尔值比较为True或False

Yes:   if greeting:

No:    if greeting == True:

Worse: if greeting is True:

当布尔值为True时,我的建议没有问题,但是在检查False时听起来很奇怪

如果我想知道变量greeting是否为False,为什么不写:

if greeting == False:

如果我写if not greeting:,它将与上面的语句有非常不同的含义。如果问候语为None怎么办?如果它是空字符串怎么办?此PEP8建议是否意味着存储布尔值的变量应仅包含True或False,并且应避免对这些变量执行None?

在我看来,这看起来像是来自其他语言的带有静态类型的推荐,并且与python不太匹配,至少与False相比。

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

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

str情况可能无关紧要。但是,如果您有在计算所有返回变量的值之前对其进行初始化的策略,则可能会发生None情况。如果在计算布尔值之前发生了一些异常,则布尔值仍为None,您可能想知道它不是被计算出来的。

但这就是is None的作用。

您的意思是我应该使用if greeting is not None and not greeting:而不是if greeting == False:还是使用以if greeting is None开头的级联ifs?

首先,您使用is None / is not None验证成功。然后,您从那里去。

您已经接受了一个答案,因为它在一个详细说明您为什么不应该这样做的原因上告诉您您想听的内容-尽管它没有给出理由或示例。您已经解雇了所有告诉您正确方法的人。显然,您只是希望"权限"以错误的方式进行操作。

en.wikipedia.org/wiki/Confirmation_bias

@Glenn Maynard:并非如此,我默认情况下选择了该答案,因为我真的没有答案,并且想关闭主题(其他答案在某种程度上是倒过来的,或多或少"这应该是很好的,因为PEP8会这样说,请忽略(实际上很少见)(不是)的情况。"这是一个严肃的答案吗?就其价值而言,我得到的最严肃的答案可能是Ignacio Vasquez-Abrams的答案(将None选作一个单独的值),但我不能选择它作为其他选择是完全删除问题,但我也不认为这是正确的行为。

您问为什么不写x == False,我给了您一个详细的答案,它彻底解释了为什么那是一个坏主意,根本没有提到PEP8。

跟随您的想法到最后。如果您说的是简单的事实,没有例外,则根本不需要存在False可分辨的值。布尔值True / None可以满足所有目的。我不同意。但是我也没有拒绝你的回答。据我了解,您只是说在大多数实际情况下,不需要区分False和其他虚假值。我同意这一点,但这还不是故事的结局。

不要使用==将布尔值与True或False进行比较。如果值可以为None或为空字符串,则此规则不适用。必须严格为True或False

@John La Roy:在我读到它时,布尔值是表达式左侧的乱码True或False。在比较的另一方面,它是一个变量,而不是一个值,并且变量的许多可能内容在表达式中等同于False。

我将其读取为"布尔值"是指greeting," True或False"是指常量(在这种情况下为RHS)。也许可以在PEP8中更清楚地表达它。

我相信您读错了。尽量不要将greeting看作是名词,而不是动词("我在问候"而不是"这是问候")。

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

One of Guido's key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code.

为此,代码应尽可能类似于书面或口头词语。在现实生活中您不会说"If I am annoying you is true, let me know",而只是说"If I am annoying you, let me know"。

这就是为什么您经常看到布尔变量(例如isOpen和hasBeenProcessed)的原因之一,因为它们有助于代码的可读性。

您绝对不应做以下事情:

if (isOpen == True)

要么:

if (customerDead == False)

仅仅因为变量名中已经有一个布尔值。给您的所有相等性是另一个布尔值,并且荒谬地调用减少,您将在哪里停下来?

if (isComplete == True) ...

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

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

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

这种修饰性的观点是正确的,但我认为它在一定程度上遗漏了这个问题。 OP正在询问说not x和x is False之间的功能差异。他似乎确实了解其中的区别,并且我认为他想知道为什么要推荐后者而不是后者。

好答案!这让我想起" Buffalo buffalo buffalo ..."

不应该是"如果我很烦你是true,请告诉我"?

@Framester非常正确,Ive根据您的建议进行了更改。感谢那。

但是,是否要检查isOpen是否为False?我应该怎么写条件语句?

@ gon1332:if not isOpen: ...。

不通过==或!=比较来比较真相的最简单原因似乎是这样的:

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说"不要这样做"的原因。

如此处所述,将is用于标识,但将==用于相等。

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

对于大多数读者来说,这种情况可能并不明显。我怀疑PEP8声称它具有潜在的误导性,这是"更糟糕的"。有时它可能是一种必要的邪恶;但是...如果您发现自己需要is True,则可能表明存在设计问题。无论如何,如果您曾经使用is,则可能应该注释"为什么"需要确切地True或False。

有趣的一点,即使它与PEP8的方向相同也不明显(PEP8指向is True的情况比== True更糟)

这是鸭子打字的一部分。在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是一个假值,但不是唯一的假值。出于避免使用isinstance的相同原因,请避免与True和False进行比较。

我理解您的意思,但是在我看来,编写g == False就像编写len(g) == 0一样,似乎是在某些情况下执行操作的正确方法。编写len(g) == 0时,我的目标通常是排除g为None的情况。在这种情况下,我是否应该依赖鸭子类型,并期望其他一些错误检测到g为None,因此没有长度?我认为这两种形式之间没有根本区别。

您为什么要排除"无"进行真相测试?将None传递给函数以代替False的有效(如果是单项的),除非在该上下文中没有专门定义None的意思。

格伦·梅纳德(Glenn Maynard):正是这一点,我经常使用3个状态布尔值,其中None表示undefined。

然后使用x is not None and not x;这通常看起来像if x is None: ... elif not x: ...。

@kriss当前对于所有不是None和false的事物,len(g) == 0可能是这种情况,但据我所知,这不能保证。 len(None)引发TypeError: object of type NoneType has no len()-因此,您不必显式检查None,而是隐式引发您或调用者需要处理的错误。如果您要专门处理None,对我来说,这似乎不如在测试中显式检查None优雅。

@pcurry:docs.python.org/3/reference/datamodel.html#object.__len__ len(g) == 0惯用语适用于具有Strait特征的所有对象(即:容器)。确实,如果要这样做,我们必须检查"无"。如果我们写if g: ...,它可以同时用于None和长度检查:stackoverflow.com/questions/7771318/

我对PEP的建议了解的方式意味着,如果您可以合理确定foo的类型(通常是这种情况),则测试显式假值是多余的,并且会降低可读性。例如,在foo = [i for i in range(10) if i == x]中,您可以肯定地确定foo可以具有的唯一假值是[](假定未引发任何异常)。在这种情况下,使用foo == []是多余的,而not foo更好。

另一方面,foo == []或foo == False的语义值有时更有价值,因此应代替(x17>)使用(IMHO)。具体取决于您要交流的内容。实际上,not foo表示" foo具有错误的值?",而foo == False表示" foo具有与False?相同的值"。

PEP声明其中包含的所有内容都是准则。规则有例外,这一规则没有什么不同。

foo == False几乎不应使用;我什至不能想到一个正确的事情。

我可以想到一个:具有类似Pickle行为的库。酸洗False与酸洗""不同。

我认为,如果foo == False,则读起来比不读foo更像是英语。

香港专业教育学院当然从未听过说英语的人说"如果今天去商店等于等于假"

@GlennMaynard:但是0 == False,所以检查确实需要是foo is False。 (PEP 8s关于== True和is True的建议在我看来总是很落后; is有时是必需的,而==在任何未知输入类型的情况下几乎总是错误的。)

推荐foo == False是糟糕的编程风格和不专业的标志之一

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

If I write if not greeting: it will have a very different meaning that the above statement. What if greeting is None ? What if it is empty string ?

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

Don't compare boolean values to True or False using ==

None或空字符串都不是布尔值。因此,如果合适,请使用greeting == False,并且greeting可以为非布尔值。

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

... Why would it sometimes be None, sometimes be a bool, and sometimes be a str? That's just asking for all sorts of trouble.

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

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表示您什么都不知道。

我通常将布尔变量命名为模式IsName,因此在您的情况下为IsGreeting。这使得检查读取为if IsGreeting / if not IsGreeting,这非常直观。

您使用if not描述的歧义是在布尔比较中使用非布尔类型的结果。通常应该避免这种情况,因为这非常令人困惑。

我基本上喜欢你,但是我在下面的评论中解释了为什么我相信没有问题。在一个完美的宇宙中没有问题。但是在现实世界中,编写if not IsGreeting:之类的语句似乎在引起麻烦,因为发生了屎。

由于这是与PEP8相关的问题... PEP8建议变量名标识符以小写字母开头,并使用下划线代替驼峰大小写。建议将驼峰式大小写字母(以大写字母开头)用作类名。

@沃尔特:很好的建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值