了解Python的“is”运算符

is运算符不匹配变量的值,而是实例本身。

这是什么意思?

我声明了两个名为xy的变量,在两个变量中赋值相同,但是当我使用is运算符时,它返回false。

我需要澄清。 这是我的代码。

 x = [1, 2, 3] y = [1, 2, 3] print x is y #It prints false! 

你误会了什么is运营商测试。 它测试两个变量是否指向相同的对象 ,而不是两个变量具有相同的值。

is运算符的文档:

运算符isis not测试对象的身份:当且仅当xy是同一个对象时, x is y是真的。

改为使用==运算符:

 print x == y 

这打印Truexy是两个单独的列表:

 x[0] = 4 print y # prints [1, 2, 3] print x == y # prints False 

如果你使用id()函数,你会看到xy有不同的标识符:

 >>> id(x) 4401064560 >>> id(y) 4401098192 

但是如果你将y赋给x那么它们都指向同一个对象:

 >>> x = y >>> id(x) 4401064560 >>> id(y) 4401064560 >>> x is y True 

并显示两者是相同的对象,则返回True

另一个重复的问是为什么两个相等的字符串通常是不相同的,这不是真的在这里回答:

 >>> x = 'a' >>> x += 'bc' >>> y = 'abc' >>> x == y True >>> x is y False 

那么,他们为什么不是同一个字符串呢? 特别是给了这个:

 >>> z = 'abc' >>> w = 'abc' >>> z is w True 

我们暂时放下第二部分。 第一个怎么可能是真的?

解释器必须有一个“实际表”(一个将字符串值映射到字符串对象的表),所以每次尝试创建一个带有'abc'内容的新字符串时,都会返回相同的对象。 维基百科有关如何实习的更详细的讨论。

而Python 一个字符串实习表; 您可以使用sys.intern方法手动实习字符串。

事实上,Python 允许自动实习任何不可变的类型,但不是必需的 。 不同的实现会实习不同的值。

CPython(你使用的实现,如果你不知道你正在使用的实现)自动实现小整数和一些特殊的单例如False ,但不是字符串(或大整数,或小元组,或其他任何东西)。 你可以很容易地看到这一点:

 >>> a = 0 >>> a += 1 >>> b = 1 >>> a is b True >>> a = False >>> a = not a >>> b = True a is b True >>> a = 1000 >>> a += 1 >>> b = 1001 >>> a is b False 

好的,但为什么zw相同?

这不是解释器自动实习,这是编译器折叠值。

如果相同的编译时字符串在同一个模块中出现两次(这意味着什么是难以定义的 – 它不是一个字符串文字,因为r'abc''abc''a' 'b' 'c' r'abc' 'a' 'b' 'c'是所有不同的文字,但是相同的字符串,但直观易懂),编译器将只创建一个字符串实例,带有两个引用。

事实上,编译器可以更进一步:优化器可以将'ab' + 'c'转换为'abc' ,在这种情况下,它可以与同一个模块中的'abc'常量一起折叠。

再一次,这是Python允许的,但不是必须的。 但是在这种情况下,CPython总是折叠小的字符串(也是小的元组)。 (尽管交互式解释程序的声明式语句编译器并不像“一次一个模块”编译程序那样运行相同的优化,所以交互式地看不到完全相同的结果。)


那么,作为程序员,你应该怎么做呢?

呃…什么都没有 如果两个不可变的值是相同的,那么几乎没有任何理由关心。 如果你想知道什么时候可以使用a is b而不是a == b ,那么你问的是错误的问题。 只是总是使用a == b除了两种情况:

  • 为了更多的可读性的比较,像x is None这样的单例值x is None
  • 对于可变值,当你需要知道变异x是否会影响y

只有当它们实际上是同一个对象时才返回true。 如果他们是一样的,那么另一个也会出现一个变化。 这是一个差异的例子。

 >>> x = [1, 2, 3] >>> y = [1, 2, 3] >>> print x is y False >>> z = y >>> print y is z True >>> print x is z False >>> y[0] = 5 >>> print z [5, 2, 3] 

一个重复的问题提示,这个比喻可能工作:

 # - Darling, I want some pudding! # - There is some in the fridge. pudding_to_eat = fridge_pudding pudding_to_eat is fridge_pudding # => True # - Honey, what's with all the dirty dishes? # - I wanted to eat pudding so I made some. Sorry about the mess, Darling. # - But there was already some in the fridge. pudding_to_eat = make_pudding(ingredients) pudding_to_eat is fridge_pudding # => False 

isis not Python中的两个身份运算符。 is运算符不会比较变量的值,而是比较变量的身份。 考虑这个:

 >>> a = [1,2,3] >>> b = [1,2,3] >>> hex(id(a)) '0x1079b1440' >>> hex(id(b)) '0x107960878' >>> a is b False >>> a == b True >>> 

上面的例子显示了ab (即使它们的值相同)身份(也可以是Cpython中的内存地址)是不同的。 这就是为什么当你说a is b ,由于两个操作数的身份不匹配,它会返回错误。 然而,当你说a == b ,它返回true,因为==操作只验证两个操作数是否具有相同的值。

有趣的例子(额外的等级):

 >>> del a >>> del b >>> a = 132 >>> b = 132 >>> hex(id(a)) '0x7faa2b609738' >>> hex(id(b)) '0x7faa2b609738' >>> a is b True >>> a == b True >>> 

在上面的例子中,即使ab是两个不同的变量, a is b返回True 。 这是因为a的类型是int ,它是一个不可变的对象。 所以Python(我想保存内存)分配相同的对象时,它是用相同的值创建。 所以在这种情况下,匹配的变量的身份和a is b证明是True

这将适用于所有不可变对象:

 >>> del a >>> del b >>> a = "asd" >>> b = "asd" >>> hex(id(a)) '0x1079b05a8' >>> hex(id(b)) '0x1079b05a8' >>> a is b True >>> a == b True >>> 

希望有所帮助。

x is yid(x) == id(y) ,比较对象的标识。

X指向一个数组,Y指向一个不同的数组。 那些数组是相同的,但是is运算符会查看那些不相同的指针。

正如你可以在这里检查一个小整数。 高于257的数字不是一个小数,所以它被计算为一个不同的对象。

在这种情况下,最好使用==

更多的信息在这里: http : //docs.python.org/2/c-api/int.html

它比较对象标识,也就是变量是否指向内存中的同一个对象。 这就像Java或C中的== (当比较指针时)。