我认为我完全理解这一点,但我只是想确保,因为我一直看到有人说永远不会对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”而不是“==”时评估我的预期方式。我错了吗?
沿着同样的路线,修改有时返回None的函数会更加pythonic,以便它们引发错误吗?假设我有一个名为“get_attr()”的实例方法,它从某个文件中检索属性。如果它发现我请求的属性不存在则返回None是否合适?让他们提出错误并在以后发现它会更好吗?
答案 0 :(得分:62)
建议不要使用 True
,False
或None
。只是你不应该使用if x == True
。
if x == True
很愚蠢,因为==
只是一个二元运算符!它的返回值为True
或False
,具体取决于其参数是否相等。如果if condition
为真,condition
将继续进行。因此,当您编写if x == True
时,Python将首先评估x == True
,如果True
为x
则为True
,否则为False
,然后如果结果为真则继续。但是,如果您希望x
成为True
或False
,为什么不直接使用if x
!
同样,x == False
通常可以替换为not x
。
在某些情况下,您可能希望使用x == True
。这是因为if
语句条件是在布尔上下文"中评估的。看看它是不是" truthy"而不是完全针对True
进行测试。例如,非空字符串,列表和字典都被if语句认为是真实的,以及非零数字值,但这些都不等于True
。因此,如果您想测试任意值是否完全值True
,而不仅仅是它是否真实,何时使用if x == True
。但我几乎从来没有看到过这方面的用途。它非常罕见,如果你做需要写它,那么值得添加评论,以便未来的开发人员(包括可能你自己)不要假设{ {1}}是多余的并将其删除。
使用== True
实际上更糟糕。永远不要将x is True
与基本的内置不可变类型(如布尔值(is
,True
),数字和字符串一起使用。原因是对于这些类型,我们关注值,而不是身份。 False
测试这些类型的值是否相同,而==
始终测试身份。
测试身份而不是值是错误的,因为理论上实现可以构造新的布尔值而不是找到现有的布尔值,导致您有两个is
值具有相同的值但存储在不同的内存中并有不同的身份。在实践中,我非常确定True
和True
总是被Python解释器重复使用,所以这不会发生,但这确实是一个实现细节。这个问题一直伴随着字符串,因为直接出现在程序源中的短字符串和文字字符串被Python回收,因此False
总是返回'foo' is 'foo'
。但是以两种不同的方式构造相同的字符串很容易,Python让它们具有不同的身份。请注意以下事项:
True
编辑:事实证明,Python在布尔值上的平等有点出乎意料(至少在我看来):
>>> stars1 = ''.join('*' for _ in xrange(100))
>>> stars2 = '*' * 100
>>> stars1 is stars2
False
>>> stars1 == stars2
True
正如the notes when bools were introduced in Python 2.3.5中所解释的那样,基本原理是使用整数1和0来表示True和False的旧行为是好的,但我们只是想要更多描述性的名称来表示我们想要代表真理的数字值。
实现这一目标的一种方法是在内置函数中简单地使用>>> True is 1
False
>>> True == 1
True
>>> True == 2
False
>>> False is 0
False
>>> False == 0
True
>>> False == 0.0
True
和True = 1
;然后1和True真的无法区分(包括False = 0
)。但这也意味着返回is
的函数会在交互式解释器中显示True
,所以完成的是创建1
作为{{1}的子类型}。关于bool
的唯一不同之处是int
和bool
; str
个实例仍然与repr
个实例具有相同的数据,并且仍以相同的方式比较相等,因此bool
。
因为int
可能是由某些代码设置的True == 1
使用x is True
所以错误,因为#34; True只是拼写1"的另一种方式,因为有很多方法可以构造等于x
但不具有相同身份的值:
True
当>>> a = 1L
>>> b = 1L
>>> c = 1
>>> d = 1.0
>>> a == True, b == True, c == True, d == True
(True, True, True, True)
>>> a is b, a is c, a is d, c is d
(False, False, False, False)
可能是任意Python值并且您只想知道它是否是布尔值x == True
时,使用x
是错误的。我们唯一确定的是,当你只想测试"真实性时,只使用True
是最好的。值得庆幸的是,通常只需要这一切,至少在我写的代码中!
更确定的方式是x
。但是,对于一个相当模糊的案例,它变得非常冗长。通过进行明确的类型检查,它看起来也不像Pythonic ......但是当你试图精确地测试x == True and type(x) is bool
而不是真正的时候,这就是你正在做的事情。 duck typing方式是接受truthy值并允许任何用户定义的类声明自己是真实的。
如果你正在处理这个非常精确的真理概念,你不仅不认为非空集合是真实的,而且也不要认为1是真的,那么只需使用True
可能没问题,因为大概你知道x is True
并非来自认为1为真的代码。我不认为有任何纯粹的蟒蛇方式来提出另一个x
生活在不同的内存地址(尽管你可以从C中做到),所以这不应该&#39尽管从理论上来说是错误的,但是它还是会被打破。要做的事。
我以前认为布尔很简单!
结束修改
但是,在True
的情况下,成语是使用None
。在许多情况下,您可以使用if x is None
,因为if not x
是" falsey"值为None
语句。但是,如果您想要以同样的方式处理所有虚假值(零值数字类型,空集合和if
),那么最好只执行此操作。如果您正在处理的值是某个可能的其他值,或None
表示"没有值" (例如当一个函数在失败时返回None
),然后它 更好地使用None
,这样你就不会意外地承担这个功能它只是碰巧返回一个空列表或数字0时失败。
我使用if x is None
而不是==
来表示不可变值类型的论点建议您使用is
而不是if x == None
。但是,在if x is None
的情况下,Python明确保证整个Universe中只有一个None
,而正常的惯用Python代码使用None
。
关于是否返回is
或引发异常,它取决于上下文。
对于类似None
示例的内容,我希望它会引发异常,因为我会像get_attr
一样调用它。调用者的正常期望是他们获取属性值,并让他们得到do_something_with(get_attr(file))
并假设属性值比忘记处理异常时更危险如果找不到该属性。另外,返回None
表示失败意味着None
不是属性的有效值。在某些情况下,这可能是个问题。
对于像None
这样的假想函数,我们提供了一个模式,它会检查多个地方以查看是否匹配,如果找到一个或see_if_matching_file_exists
,它可以返回匹配如果它没有。但另外它可以返回一个匹配列表;然后,没有匹配只是空列表(这也是"假的&#34 ;;这是我只是使用None
来查看我是否有任何回报的情况之一。 / p>
因此,当在异常和if x
之间进行选择以指示失败时,您必须确定None
是否是预期的非失败值,然后查看调用该函数的代码的期望。如果"正常"期望是会返回一个有效值,并且只有在调用者能够正常工作(无论是否返回有效值)时,您应该使用异常来指示失败。如果没有有效值是很常见的,那么调用者将期望处理这两种可能性,然后你可以使用None
。
答案 1 :(得分:13)
使用if foo
或if not foo
,无需==
或is
。
要检查无,建议使用is None
和is not None
。这允许您将其与False(或评估为False的内容区分开来,例如""
和[]
)。
get_attr
是否应返回None
取决于上下文。您可能有一个值为None的属性,您将无法执行此操作。我会将None
解释为“未设置”,而KeyError
则表示该文件中不存在该密钥。
答案 2 :(得分:7)
如果检查真相:
if foo
表示错误:
if not foo
表示无:
if foo is None
表示非人:
if foo is not None
对于getattr()
,正确的行为不会返回None
但会引发AttributError
错误 - 除非您的类类似于defaultdict
答案 3 :(得分:6)
关于是否提出异常或返回None
:这取决于用例。两者都可以是pythonic。例如,查看python的dict
类,x[y]
挂钩到dict.__getitem__
,如果不存在,则会引发KeyError
。但是如果key不存在,dict.get
方法返回第二个参数(默认为None
)。 它们都很有用。
要考虑的最重要的事情是在docstring中记录该行为,并确保您的get_attr()
方法完成它所说的功能。
要解决您的其他问题,请使用以下约定:
if foo:
# for testing truthiness
if not foo:
# for testing falsiness
if foo is None:
# testing .. Noneliness ?
if foo is not None:
# check explicitly avoids common bugs caused by empty sequences being false
返回True
或False
的函数应该有一个名称,可以明显改善代码的可读性
def is_running_on_windows():
return os.name == 'nt'
在python3中,你可以“输入提示”:
>>> def is_running_on_windows() -> bool:
... return os.name == 'nt'
...
>>> is_running_on_windows.__annotations__
{'return': bool}
答案 4 :(得分:1)
您可以直接检查该变量是否包含值if var
或not var
。
答案 5 :(得分:1)
在PEP 8(Style Guide for Python Code) document的示例中,我看到正在使用foo is None
或foo is not None
而不是foo == None
或foo != None
。此文档中建议使用if boolean_value
,而不是if boolean_value == True
或if boolean_value is True
。所以我认为如果这是官方的Python方式,我们Python的人也应该这样做。
问候。
答案 6 :(得分:0)
对于虚构的getattr
函数,如果请求的属性始终可用但不是,则抛出错误。如果该属性是可选的,则返回None
。
答案 7 :(得分:0)
表示True,而不是None:
if foo:
表示错误,无:
if not foo:
答案 8 :(得分:0)
要确保的一件事是没有任何东西可以重新分配你的变量。如果它最终不是布尔值,依赖真实性将导致错误。动态类型语言中条件编程的美妙之处:)。
以下打印" 否"。
x = False
if x:
print 'yes'
else:
print 'no'
现在让我们改变 x 。
x = 'False'
现在声明打印" 是"因为这个字符串是真的。
if x:
print 'yes'
else:
print 'no'
但是,此声明正确输出" 否"。
if x == True:
print 'yes'
else:
print 'no'