我想我完全理解这一点,但我只想确定,因为我一直看到人们说,永远不要对True
、False
或None
进行测试。
他们建议例程应该引发错误,而不是返回False或None。无论如何,我有很多情况,我只是想知道是否设置了标志,所以我的函数返回True或False。在其他情况下,如果没有有用的结果,我有一个函数返回None。从我的想法来看,只要我意识到我不应该使用:
if foo == True
if foo == False
if foo == None
而应该使用:
if foo is True
if foo is False
if foo is None
因为True、False和None都是单例的,并且在使用“is”而不是“==”时总是按照我期望的方式进行计算。我错了吗?
同样,修改那些有时不返回任何值的函数,从而导致它们产生错误,这会更像是一种恶作剧吗?
假设我有一个名为“get_attr()”的实例方法,它从某个文件检索属性。如果发现我请求的属性不存在,是否应该返回None?最好让他们提出一个错误,然后再抓住它?
建议不是永远不要使用
True
、False
或None
。只是你不应该使用if x == True
。if x == True
是愚蠢的,因为==
只是一个二进制运算符!它的返回值为True
或False
,这取决于它的参数是否相等。如果condition
为真,则if condition
将继续。因此,当您编写if x == True
时,Python将首先计算x == True
,如果x
是True
,否则将变成True
,如果结果是真的,则继续。但是如果您希望x
是True
或False
,为什么不直接使用if x
!同样,
x == False
通常可以被not x
替换。在某些情况下,您可能需要使用
x == True
。这是因为if
语句条件是“在布尔上下文中求值”的,以查看它是否是“truthy”,而不是完全针对True
进行测试。例如,非空字符串、列表和字典都被if语句视为truthy,也被视为非零数值,但它们都不等于True
。所以,如果你想测试一个任意的值是否是True
的值,而不仅仅是它是否真实,当你使用if x == True
时。但我几乎看不到它的用处。如果你真的需要写这篇文章,那么添加一条评论是非常罕见的,这样未来的开发人员(可能包括你自己)就不会认为== True
是多余的,然后删除它。相反,使用
x is True
实际上更糟。决不能将is
与基本的内置不可变类型(如布尔值(True
,False
)、数字和字符串一起使用。原因是,对于这些类型,我们关心的是值,而不是标识。==
测试这些类型的值是否相同,而is
始终测试标识。测试标识而不是值是不好的,因为一个实现在理论上可以构造新的布尔值,而不是去寻找现有的布尔值,这会导致有两个具有相同值的
True
值,但它们存储在内存中的不同位置,并且具有不同的标识。在实践中,我非常确定Python解释器总是重用True
和False
,因此不会发生这种情况,但这确实是一个实现细节。这个问题总是让人们对字符串感到困惑,因为直接出现在程序源代码中的短字符串和文本字符串被Python回收,所以'foo' is 'foo'
总是返回True
。但是很容易用两种不同的方法构造同一个字符串,并让Python赋予它们不同的标识。注意以下事项:编辑:因此,Python在布尔上的相等性有点出乎意料(至少对我来说):
正如the notes when bools were introduced in Python 2.3.5中所解释的,其基本原理是,使用整数1和0来表示真值和假值的旧行为是好的,但我们只希望对表示真值的数字使用更具描述性的名称。
实现这一点的一种方法是在内置代码中简单地包含
True = 1
和False = 0
;然后1和True将无法区分(包括is
)。但这也意味着返回True
的函数将在交互式解释器中显示1
,因此我们所做的是将bool
创建为int
的子类型。关于bool
唯一不同的是str
和repr
;bool
实例仍然具有与int
实例相同的数据,并且仍然以相同的方式比较相等,因此True == 1
。因此,当
x
可能被某些代码设置为“True只是拼写1的另一种方式”时,使用x is True
是错误的,因为有很多方法可以构造等于True
但不具有相同标识的值:你错了se
x == True
当x
可以是任意Python值时,您只想知道它是否是布尔值True
。我们唯一确定的是,当您只想测试“真实性”时,最好使用x
。谢天谢地,这通常是所有需要的,至少在我写的代码中!更可靠的方法是
x == True and type(x) is bool
。但对于一个不太清楚的案子来说,这就太冗长了。通过执行显式类型检查,它看起来也不太像Python。。。但是,当您试图精确地测试True
而不是truthy时,您所做的就是这样;duck类型的方法是接受truthy值,并允许任何用户定义的类声明自己是truthy的。如果您正在处理这个非常精确的真理概念,其中您不仅不认为非空集合是真的,而且也不认为1是真的,那么只使用
x is True
可能是可以的,因为您大概知道x
不是来自于认为1为真的代码。我不认为有任何纯python的方法可以产生另一个True
,它位于不同的内存地址(尽管您可能可以从C中完成它),因此这不应该中断,尽管理论上是“错误的”事情。我以前认为布尔人很简单!
结束编辑
然而,对于
None
,习惯用法是使用if x is None
。在许多情况下,您可以使用if not x
,因为None
是if
语句的“false”值。但是,如果您希望以相同的方式处理所有错误的值(零值数值类型、空集合和None
),最好这样做。如果处理的值可能是其他值,也可能是指示“无值”的None
(例如,当函数失败时返回None
),那么最好使用if x is None
,这样就不会在函数恰好返回空列表或数字0时意外假设函数失败。我关于对不可变值类型使用
==
而不是is
的参数建议您应该使用if x == None
,而不是if x is None
。然而,在None
的情况下,Python确实显式地保证整个宇宙中只有一个None
,并且普通的Python惯用代码使用is
。关于是返回
None
还是引发异常,这取决于上下文。对于您的
get_attr
示例,我希望它引发异常,因为我将像do_something_with(get_attr(file))
那样调用它。调用者通常的期望是,他们会得到属性值,让他们得到None
,并假设是属性值,这比在找不到属性时忘记处理异常要危险得多。另外,返回None
表示失败意味着None
不是属性的有效值。在某些情况下,这可能是一个问题。对于像
see_if_matching_file_exists
这样的虚函数,我们提供一个模式给它,它检查几个地方看是否有匹配,如果找到一个,它可以返回一个匹配,如果没有,它可以返回None
。但是它也可以返回一个匹配列表;那么没有匹配只是空列表(这也是“false”;在这种情况下,我只需要使用if x
来查看是否有任何东西回来。因此,当在异常和
None
之间进行选择以指示失败时,必须确定None
是否是预期的非失败值,然后查看调用函数的代码的预期值。如果“正常”的期望是返回一个有效值,并且只有偶尔调用方能够正常工作,无论是否返回有效值,那么您应该使用异常来指示失败。如果没有有效值是很常见的,那么调用者将期望处理这两个possi概率,然后可以使用None
。使用
if foo
或if not foo
。这不需要==
或is
。如果不检查,建议使用
is None
和is not None
。这允许您将其与False(或计算为False的事物,如""
和[]
)区分开来。get_attr
是否应该返回None
取决于上下文。您可能有一个值为“无”的属性,但您无法这样做。我会将None
解释为“unset”,而KeyError
则表示密钥不存在于文件中。如果核实事实:
对于错误:
对于无:
对于非无:
对于} 。
getattr()
来说,正确的行为是返回None
而不是返回^{,而是引发一个AttributError
错误,除非您的类类似于^{相关问题 更多 >
编程相关推荐