在python结尾PEP8我正在读:
请勿使用==
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:
更糟糕?
答案 0 :(得分:16)
我相信你读错了。尽量不要将greeting
视为名词而不是动词(“我在问候”而不是“这是问候语”)。
您可以在PEP8的序言中看到线索:
Guido的一个重要见解是,代码的读取频率远高于编写代码。此处提供的准则旨在提高代码的可读性。
为此,代码应尽可能类似于书面或口头的单词。你现实生活中没有说"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)
只是因为你已经在变量名中有一个布尔值。所有相等都给你另一个布尔值,并调用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
,则需要完全 False
或is
。
答案 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 greeting
和greeting == False
具有不同的含义。但是PEP8并不是说相反的意思,也不是说不使用greeting == False
。它说:
请勿使用==
将布尔值的值与True或False进行比较
None
和空字符串都不是布尔值。因此,请适当使用greeting == False
,而greeting
可以是非布尔值。
有人在您的问题下方发表了评论:
...为什么有时有时是None,有时是布尔,有时是str?那只是在问各种各样的麻烦。
不是。这是一个用例:您有一个患者数据库,其中有一个字段说明患者是否死于自杀。假设我们有Patient
类,属性为suicide
。 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
表示您什么都不知道。
答案 5 :(得分:0)
我通常在模式IsName
之后命名我的布尔变量,所以在你的情况IsGreeting
。这使支票读取if IsGreeting
/ if not IsGreeting
,这非常直观。
您使用if not
描述的歧义是在布尔比较中使用非布尔类型的结果。这通常应该避免,因为它非常混乱。