261

当我比较时我的编辑器会警告我my_var == None,但在我使用时没有警告my_var is None

我在 Python shell 中进行了测试,并确定两者都是有效的语法,但我的编辑器似乎说这my_var is None是首选。

是这样吗?如果是这样,为什么?

4

6 回答 6

318

概括:

is当您想要检查对象的身份时使用(例如检查是否varNone)。==当您想检查相等性时使用(例如var等于3?)。

解释:

您可以拥有my_var == None将返回的自定义类True

例如:

class Negator(object):
    def __eq__(self,other):
        return not other

thing = Negator()
print thing == None    #True
print thing is None    #False

is检查对象身份。只有 1 个对象None,所以当你这样做时my_var is None,你正在检查它们是否实际上是同一个对象(不仅仅是等效对象)

换句话说,==是检查等价性(从对象到对象定义),而is检查对象身份:

lst = [1,2,3]
lst == lst[:]  # This is True since the lists are "equivalent"
lst is lst[:]  # This is False since they're actually different objects
于 2013-01-09T22:08:04.063 回答
159

is在将任意对象与单例对象进行比较时,通常首选None它,因为它更快且更可预测。is总是按对象身份进行比较,而==做什么取决于操作数的确切类型,甚至取决于它们的顺序。

此建议得到PEP 8的支持,它明确指出“与 None 等单例的比较应该始终使用isor is not,而不是相等运算符。”

于 2013-01-09T22:10:46.273 回答
13

isPEP 8 定义在比较单例时最好使用运算符。

于 2013-01-09T22:11:07.670 回答
6

我最近遇到了可能出错的地方。

import numpy as np
nparray = np.arange(4)

# Works
def foo_is(x=None):
    if x is not None:
        print(x[1])

foo_is()
foo_is(nparray)

# Code below raises 
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
def foo_eq(x=None):
    if x != None:
        print(x[1])

foo_eq()
foo_eq(nparray)

我创建了一个函数,它可以选择将一个 numpy 数组作为参数,如果包含它,它会发生变化。如果我使用不等式运算符测试它是否包含!=,则会引发 ValueError (参见上面的代码)。如果我使用is not none,代码可以正常工作。

于 2021-04-09T14:15:02.743 回答
0

“==”与“is”不同的另一个例子。当您从数据库中提取信息并检查值是否存在时,结果将是值或无。

看看下面的 if 和 else。当数据库返回“无”时,只有“是”有效。如果你用 == 代替,if 语句将不起作用,它会直接转到 else,即使结果是“无”。希望我能说清楚。

conn = sqlite3.connect('test.db')
c = conn.cursor()
row = itemID_box.get()

# pull data to be logged so that the deletion is recorded
query = "SELECT itemID, item, description FROM items WHERE itemID LIKE '%" + row + "%'"
c.execute(query)
result = c.fetchone()

if result is None:
    # log the deletion in the app.log file
    logging = logger('Error')
    logging.info(f'The deletion of {row} failed.')
    messagebox.showwarning("Warning", "The record number is invalid")
else:
    # execute the deletion
    c.execute("DELETE from items WHERE itemID = " + row)
    itemID_box.delete(0, tk.END)
    messagebox.showinfo("Warning", "The record has been deleted")
    conn.commit()
    conn.close()
于 2021-06-26T23:08:42.207 回答
-3

我们可以以打印功能为例。看这里:

print(print())
print(None)

两者都输出无:

None
None

is指的是实际的东西,无论它们是对象none。打印不是对象none。

print(None is print)
print(None is None)

现在我们得到了想要的结果。

False
True

PEP 8 也提到了这一点,说“与像 None 这样的单例的比较应该总是用 is 或 not 来完成,而不是相等运算符。”

is也更快。

于 2021-05-18T19:15:01.490 回答