2012-04-19 102 views
5

风格指南http://www.python.org/dev/peps/pep-0008为什么没有真正的==真:

的最后一个点读...

布尔值,不要比较,真或假使用==。

为什么?

编辑 只是要清楚什么IM要求(和它的指示问题本身的),当你写

if something: 
    print "something is true" 

你正在做一个隐式转换为布尔值可能会或可能不会根据工作关于什么是真正意义。恕我直言,这种形式的编程是不鼓励的,因为它可能导致的副作用。

numberOfApples = -1 
if numberOfApples: 
    print "you have apples" # is not what is intended. 

if numberOfApples == True: 
    print "you have apples" # is also not what is intended. 

iHaveApples = numberOfApples > 0 
if iHaveApples is True: # Edit: corrected this.. the "is" is better than the == 
    print "you have apples" # is correct. 

隐式转换会掩盖逻辑错误。那么为什么风格指南鼓励这个呢?

+0

我开始认为布尔测试的最佳样式被标记为样式指南中最差的样式。 如果numberOfApples为True: 将清除numberOfApples不是一个布尔值。 – 2012-04-19 19:40:06

+0

那么你真正想要的是比较如果x是bool()类型,如果它是,如果它是真或假 – 2012-04-22 16:50:47

+0

@PedroWerneck正确。因此,风格指南错误地说,测试bool的最糟糕的方式是如果bool_type是[True | False]:因为它实际上是最好的方式 – 2012-04-23 14:55:33

回答

7

这意味着你应该写

if greeting: 

相反的:

if greeting == True: 

同样,你不应该写这两种:

if (greeting == True) == True: 

额外的测试是多余的,不要为代码添加任何值,所以应该删除它们。

+3

人们无法得到布尔值,这真是太神奇了。例如“bool Predicate(){if(condition)return true; else return false;}” - 什么?这可以写成简单的“bool Predicate(){return condition;}”! – Asik 2012-04-19 06:28:57

+0

不幸的是,当语言支持真实性/虚假性的其他值时,您使用的确切语句可以彻底改变程序的含义......像'__eq__','__nonzero__'和'__len__'这样的特殊函数只会让事情变得更糟,是的,但有时会出现问题) – mgibsonbr 2012-04-19 06:37:33

+2

@mgibsonbr您可以使用'bool'将值强制为一个布尔值。 – Marcin 2012-04-19 06:38:56

1

因为它是多余的。

if hasChildren: 

相同

if hasChildren == True: 

,但简短,更易于阅读。

+0

if numberOfChildren:如果答案不为零,那么print True将返回true。即使它是负面的。隐式转换为布尔值具有副作用,通常不鼓励。然而,风格指南鼓励隐式转换为布尔。 – 2012-04-19 13:44:43

+0

@PeterMoore,你误解了风格指南。 '如果numberOfChildren> 0:'完全是pythonic,但是if(numberOfChildren> 0)== True:'不是。 – 2012-04-23 06:29:39

+0

@Bago我完全同意if(numberOfChildern> 0)== True:是多余的,因为比较器“>”将明确地使左侧为布尔类型。但是,如果使用unknown_type:与样式指南相反,则不如使用“is”进行测试安全。测试bool“是”bool比bool更好:或者如果bool == bool:因为在python中发生的真值重载,你不会得到一个false真。我真的在说什么。 – 2012-04-23 14:47:36

2

恕我直言,指导风格的一点是要以一种合理的方式来标准化一些常见的结构,所以你最终不会做出最终会做同样事情的非常不同的陈述。更多的是,这些不寻常的形式可能表明程序员有理由以不同的方式做事,也许他试图实现与陈述不同的东西。

如果您想测试陈述的真实性/虚假性,只需使用陈述本身或在not之前。如果您必须确保该声明的评估结果为TrueFalse(不仅仅是真/假值),您可以使用statement is True - 虽然样式指南不鼓励它或者检查其类型(使用isinstance)。但这通常是不好的设计,除非你有充分的理由这样做,否则你应该避免这种情况。

使用statement == True是有危险的,原因很多:1)仅适用于True,与其他“真值”(例如[1])失败; 2)如果语句返回的值重新定义了__eq__,则可能会产生意想不到的结果; 3)如果参数的顺序改变等,可能会产生不同的结果。请注意,如果值实现__nonzero____len__,则仅使用该语句也可能返回不同的真实/虚假值,但对于常规使用而言通常不会造成问题。

一些例子,说明如何搞砸事情都可以,如果你从风格偏离:

if True: print True # True 
if 1: print True # True 
if [1]: print True # True 

True is True # True 
1 is True # False 
[1] is True # False 

True == True # True 
1 == True # True 
[1] == True # False 

编辑:一些:

if 1: print True # True 
if 2: print True # True 

1 == True # True 
2 == True # False 

1 is True # False 
2 is True # False 

更新:为@Marcin指出,您可以使用bool将值强制为True/False,保证只有这些值才会出现。该函数的结果与该值的默认真实/虚假性一致(因此将__nonzero____len__考虑在内)。一些例子:

if bool(1): print True # True 
bool(1) == True  # True 
bool(1) is True  # True 

if bool(2): print True # True 
bool(2) == True  # True 
bool(2) is True  # True 

1 or 2    # 1 
1 and 2    # 2 
bool(1) or bool(2) # True 
bool(1) and bool(2) # True 

bool(1) == bool(2) # True 
bool(1) is bool(2) # True 
+0

我很欣赏你的意见,这是一个明确的转换。我的牛肉(因为它在哪里)是风格指南鼓励我认为马虎的副作用通过严格的显式转换隐含转换的地方。我不认为(例如)一个容器是真或假。对我来说,重载一个这样的真理意味着它不是空的是没有多大意义的。 – 2012-04-19 14:41:59

+0

这是主观的恕我直言,某些语言(如Java)鼓励以明显的转换为理由,减少错误的窗口,其他语言鼓励DWIM行为以增加语言表达能力。在C语言中将数字视为假/真,如果它们为零/非零是常见做法,将空容器(列表,字符串和集合)视为false在Lisp中很常见,并且这两种做法都有优点和缺点。重要的是语言要一致地实施所选择的策略(对比JavaScript,例如,“”是错误的,但[]是真实的)。 – mgibsonbr 2012-04-19 23:39:20

+0

我不认为使用bool(unknown_type)会有与使用unknown_type“is”[False | True]相同的效果,例如如果T = -1那么它不是True,按照约定0 = False 1 = True并且type是一个bool。所以测试在布尔状态测试中给出了错误的结果。 – 2012-04-23 15:20:48

0

在排序:

# A, Good: 
if numberOfApples > 0: 
    print "you have apples" 

# B, Also good: 
iHaveApples = numberOfApples > 0 
if iHaveApples: 
    print "you have apples" 

# C, Bad: 
iHaveApples = numberOfApples > 0 
if iHaveApples == True: 
    print "you have apples" 

为什么你会永远挑下在A或B?

更新:

我想你出汗多一些极端情况的子弹,但如果这些极端情况在您的项目无论用适当的比较。一般来说,我们知道iHaveApples的类型,例如我们知道这是使用>进行比较的结果。我相信,在代码中使用这些信息是合理的,也是一种很好的做法。如果你问,“如果我认为这是一个傻瓜,结果是一个整数或其他东西。”比我想说的你的代码中有一个bug,你应该找到它,修正它,并写一个测试,以防再犯同样的错误。不要依靠python在运行时找到你的错误。

我就断言,并留下你来证明,如果你想,那if iHaveApples:的行为完全一致,但运行速度更快,因为if iHaveApples is True:当你知道肯定iHaveApples是一个布尔值。最后,我会举例说明is何时会导致不良行为,至少在我看来。

>>> import numpy 
>>> totalApples = numpy.sum([1, 2, 3]) == 6 
>>> totalApples 
True 
>>> totalApples is True 
False 

我会让你找出原因,如果你想(提示,检查type(totalApples))不起作用。

+1

我认为C也不是很正确,但它应该是“是”而不是==。所以如果iHaveApples是真的比任何其他表达方式更真实。我绝对不认为它应该是风格指南吸取的方式。 – 2012-04-23 14:13:43

+1

顺便说一下B不好,除非你知道你正在比较一个布尔值。你怎么知道这个类型在if语句中是一个bool?如果你认为你比较一个bool而不是bool,那么隐式转换问题只会提高它的头。这就是为什么我选择-1的numberOfApples为我的例子。还有为什么我用> comparitor做了一个布尔值。样式指南正在讨论显式测试布尔值,并且其测试不够安全。 – 2012-04-23 16:13:10

+0

@PeterMoore,看我的更新 – 2012-04-24 01:20:35