为什么“is”关键字不在这里工作? [重复]

时间:2021-07-08 07:03:15

This question already has an answer here:

这个问题在这里已有答案:

I know that is is used to compare if two objects are the same but == is for equality. From my experience is always worked for numbers because Python reuse numbers. for example:

我知道这是用来比较两个对象是否相同,但==是为了相等。根据我的经验总是适用于数字,因为Python重用数字。例如:

>>>a = 3
>>>a is 3
True

And I'm used to using is whenever I compare something to a number. But is didn't work for this program below:

每当我将某些东西与数字进行比较时,我习惯使用它。但是下面这个程序没有用:

from collections import namedtuple
# Code taken directly from [Udacity site][1].
# make a basic Link class
Link = namedtuple('Link', ['id', 'submitter_id', 'submitted_time', 'votes',
                           'title', 'url'])

# list of Links to work with
links = [
    Link(0, 60398, 1334014208.0, 109,
         "C overtakes Java as the No. 1 programming language in the TIOBE index.",
         "http://pixelstech.net/article/index.php?id=1333969280"),
    Link(1, 60254, 1333962645.0, 891,
         "This explains why technical books are all ridiculously thick and overpriced",
         "http://prog21.dadgum.com/65.html"),
    Link(23, 62945, 1333894106.0, 351,
         "Learn Haskell Fast and Hard",
         "http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/"),
    Link(2, 6084, 1333996166.0, 81,
         "Announcing Yesod 1.0- a robust, developer friendly, high performance web framework for Haskell",
         "http://www.yesodweb.com/blog/2012/04/announcing-yesod-1-0"),
    Link(3, 30305, 1333968061.0, 270,
         "TIL about the Lisp Curse",
         "http://www.winestockwebdesign.com/Essays/Lisp_Curse.html"),
    Link(4, 59008, 1334016506.0, 19,
         "The Downfall of Imperative Programming. Functional Programming and the Multicore Revolution",
         "http://fpcomplete.com/the-downfall-of-imperative-programming/"),
    Link(5, 8712, 1333993676.0, 26,
         "Open Source - Twitter Stock Market Game - ",
         "http://www.twitstreet.com/"),
    Link(6, 48626, 1333975127.0, 63,
         "First look: Qt 5 makes JavaScript a first-class citizen for app development",
         "http://arstechnica.com/business/news/2012/04/an-in-depth-look-at-qt-5-making-javascript-a-first-class-citizen-for-native-cross-platform-developme.ars"),
    Link(7, 30172, 1334017294.0, 5,
         "Benchmark of Dictionary Structures", "http://lh3lh3.users.sourceforge.net/udb.shtml"),
    Link(8, 678, 1334014446.0, 7,
         "If It's Not on Prod, It Doesn't Count: The Value of Frequent Releases",
         "http://bits.shutterstock.com/?p=165"),
    Link(9, 29168, 1334006443.0, 18,
         "Language proposal: dave",
         "http://davelang.github.com/"),
    Link(17, 48626, 1334020271.0, 1,
         "LispNYC and EmacsNYC meetup Tuesday Night: Large Scale Development with Elisp ",
         "http://www.meetup.com/LispNYC/events/47373722/"),
    Link(101, 62443, 1334018620.0, 4,
         "research!rsc: Zip Files All The Way Down",
         "http://research.swtch.com/zip"),
    Link(12, 10262, 1334018169.0, 5,
         "The Tyranny of the Diff",
         "http://michaelfeathers.typepad.com/michael_feathers_blog/2012/04/the-tyranny-of-the-diff.html"),
    Link(13, 20831, 1333996529.0, 14,
         "Understanding NIO.2 File Channels in Java 7",
         "http://java.dzone.com/articles/understanding-nio2-file"),
    Link(15, 62443, 1333900877.0, 1244,
         "Why vector icons don't work",
         "http://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html"),
    Link(14, 30650, 1334013659.0, 3,
         "Python - Getting Data Into Graphite - Code Examples",
         "http://coreygoldberg.blogspot.com/2012/04/python-getting-data-into-graphite-code.html"),
    Link(16, 15330, 1333985877.0, 9,
         "Mozilla: The Web as the Platform and The Kilimanjaro Event",
         "https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.planning/Y9v46wFeejA"),
    Link(18, 62443, 1333939389.0, 104,
         "github is making me feel stupid(er)",
         "http://www.serpentine.com/blog/2012/04/08/github-is-making-me-feel-stupider/"),
    Link(19, 6937, 1333949857.0, 39,
         "BitC Retrospective: The Issues with Type Classes",
         "http://www.bitc-lang.org/pipermail/bitc-dev/2012-April/003315.html"),
    Link(20, 51067, 1333974585.0, 14,
         "Object Oriented C: Class-like Structures",
         "http://cecilsunkure.blogspot.com/2012/04/object-oriented-c-class-like-structures.html"),
    Link(10, 23944, 1333943632.0, 188,
         "The LOVE game framework version 0.8.0 has been released - with GLSL shader support!",
         "https://love2d.org/forums/viewtopic.php?f=3&t=8750"),
    Link(22, 39191, 1334005674.0, 11,
         "An open letter to language designers: Please kill your sacred cows. (megarant)",
         "http://joshondesign.com/2012/03/09/open-letter-language-designers"),
    Link(21, 3777, 1333996565.0, 2,
         "Developers guide to Garage48 hackatron",
         "http://martingryner.com/developers-guide-to-garage48-hackatron/"),
    Link(24, 48626, 1333934004.0, 17,
         "An R programmer looks at Julia",
         "http://www.r-bloggers.com/an-r-programmer-looks-at-julia/")]


# links is a list of Link objects. Links have a handful of properties. For
# example, a Link's number of votes can be accessed by link.votes if "link" is a
# Link.

# make the function query() return a list of Links submitted by user 62443, by
# submission time ascending

def query():
    print "hello"
    print [link for link in links if link.submitter_id == 62443] # is does not work
    return sorted([link for link in links if link.submitter_id == 62443],key = lambda x: x[2])
query()

When I used is inside the query function like this [link for link in links if link.submitter_id is 62443] I'll get an empty list. But if I use ==, it worked fine.

当我使用的是这样的查询函数内部[链接链接链接如果link.submitter_id是62443]我将得到一个空列表。但如果我使用==,它工作正常。

For the most part, the code was directly taken from the udacity site but I also tried it on my local machine. The same result. So I think the numbers are now different objects in this case but why? Is there a need for this?

在大多数情况下,代码直接从udacity网站获取,但我也在我的本地机器上尝试过。同样的结果。所以我认为这个数字现在是不同的对象,但为什么呢?有这个需要吗?

EDIT: Yes. I admit this question is duplicate and should be closed. But it's duplicate with the first post not the second. I didn't know that question before posting this.

编辑:是的。我承认这个问题是重复的,应该关闭。但它与第一​​篇文章不同,而不是第二篇文章。在发布之前我不知道这个问题。

My problem was that I thought number objects would always be reused.

我的问题是我认为数字对象总是会被重用。

Thanks to everyone, I got rid of a bad habit.

感谢大家,我摆脱了一个坏习惯。

6 个解决方案

#1


9  

There's no answer to your question short of digging into details of the implementation of the specific version of Python you're using. Nothing is defined about whether a == b implies a is b when a and b are numbers. It's often true, and especially for "little integers", due to that CPython keeps a cache of little integer objects and usually (not always!) returns the same object for a given small integer value. But nothing about that is defined, guaranteed, or even always the same across releases.

除了深入研究您正在使用的特定Python版本的实现细节之外,您的问题没有答案。当a和b是数字时,没有定义a == b是否暗示a是b。这通常是正确的,特别是对于“小整数”,因为CPython保留了一些小整数对象的缓存,并且通常(并非总是!)为给定的小整数值返回相同的对象。但是没有任何关于它的定义,保证,甚至在各个版本中始终相同。

Thinking about memory addresses can be mildly helpful, since that's how id() is implemented in CPython. But other implementations use different implementations for id(). For example, I was told that id() was a major pain to implement in Jython (Python implemented in Java), since Java is free to move objects around in memory during garbage collection (CPython does not: in CPython an object always occupies the memory originally allocated for it, until the object becomes trash).

考虑内存地址可能会有一些帮助,因为这就是在CPython中实现id()的方式。但是其他实现对id()使用不同的实现。例如,我被告知id()是在Jython中实现的一个主要难题(用Java实现的Python),因为Java在垃圾收集期间可以*地在内存中移动对象(CPython没有:在CPython中,对象总是占用最初为它分配的内存,直到对象变为垃圾)。

The only intended - and supported - use for is is to check whether two names for objects in fact resolve to the very same object. For example, regardless of the type of b, after

唯一用于和支持的用途是检查对象的两个名称是否实际上解析为同一个对象。例如,不管b的类型如何

a = b

it must be the case that

一定是这样的

a is b

is True. And that's sometimes useful.

是真的。这有时很有用。

_sentinel = object() # create a unique object

def somefunc(optional=_sentinel):
    if optional is _sentinel:  # we know for sure nothing was passed
        ...

The other main use is for the handful of objects guaranteed to be singletons. None, True and False are examples of that, and indeed it's idiomatic to write:

另一个主要用途是保证为单身的少数对象。没有,是真是假的例子,实际上它写的是惯用的:

if a is None:

instead of:

if a == None:

The first way succeeds if and only if a is in fact bound to the the singleton None object, but the second way may succeed if a is of any type such that a.__eq__(None) returns True.

当且仅当a实际上绑定到单例None对象时,第一种方式成功,但如果a是任何类型,使得.__ eq __(None)返回True,则第二种方式可能成功。

Don't use is for numbers. That's insane ;-)

不要用于数字。那太疯狂了;-)

#2


5  

You are correct in that is checks identity, if the two variables are the same object, and that == is used to check equality, if the objects are equal. (What equal means is decided by the involved classes).

你是正确的是检查身份,如果两个变量是同一个对象,并且==用于检查相等性,如果对象是相等的。 (所涉及的等级决定了相同的手段)。

And you are correct that using is to check if two numbers are equal often works, because Python reuse numbers, so often when they are equal, they are also identical.

你是正确的,使用是检查两个数字是否相等通常是有效的,因为Python重用数字,所以通常当它们相等时,它们也是相同的。

But you do notice how that sounds. Should you check if two numbers are equal, by using the identity check? No, of course not. You should use the equality check to check if objects are equal. It's as simple as that.

但你确实注意到这听起来如何。你应该通过身份检查来检查两个号码是否相等吗?不,当然不。您应该使用相等性检查来检查对象是否相等。就这么简单。

That you often can use the identity check to check the equality of numbers is just a side-effect of Python reusing numbers, which it does to save memory, and which is an implementation detail.

您经常可以使用身份检查来检查数字的相等性只是Python重用数字的副作用,它可以节省内存,这是一个实现细节。

Besides, in Python 3 == 3.0, but 3 is not 3.0. So you should use == for that reason.

此外,在Python 3 == 3.0中,但3不是3.0。因此你应该使用==。

#3


1  

There are two parts to this question

这个问题分为两部分

  1. is does not checks for equality, it just checks for identity. Two objects have same identity iff they are same objects (with same identity i.e. id(a) == id(b))

    是不检查相等性,它只是检查身份。如果两个对象是相同的对象(具有相同的标识,即id(a)== id(b)),则它们具有相同的标识

    >>> a = 10
    >>> b = a
    >>> id(a), id(b)
    (30388628, 30388628)
    
  2. CPython as Implemented (may be for others) certain numbers range of integers within a certain limit, they are cached so even though they are different objects, yet they have the same identity

    CPython as Implemented(可能是为其他人)某些数字范围内的整数在一定限度内,它们被缓存,即使它们是不同的对象,但它们具有相同的身份

Thus

>>> a is 200
True
>>> a = 2000
>>> a is 2000
False

#4


0  

This is because is compares identities:

这是因为比较身份:

>>> a = 10
>>> id(a)
30967348
>>> id(10)
30967348
>>> a is 10
True
>>> a += 1
>>> a
11
>>> id(a)
30967336
>>> id(11)
30967336
>>> a is 11
True
>>> a = 106657.334
>>> id(a)
44817088
>>> id(106657.334)
31000752
>>> a is 106657.334
False
>>> a == 106657.334
True

#5


0  

is used to compare identity.

用于比较身份。

In [26]: a = 3

In [27]: a is 3
Out[27]: True

In [28]: id(a)
Out[28]: 140479182211448

In [29]: id(3)
Out[29]: 140479182211448

Extending same to the above example.

将其扩展到上面的例子。

In [32]: for link in links:
    print id(link.submitter_id), id(62443), id(link.submitter_id) == id(62443), link.submitter_id

....:

140479184066728 140479184065152 False 60398
140479184066872 140479184065152 False 60254
140479184065688 140479184065152 False 62945
140479184064984 140479184065152 False 6084
140479184064648 140479184065152 False 30305
140479184063416 140479184065152 False 59008
140479184063608 140479184065152 False 8712
140479184063752 140479184065152 False 48626
140479184064352 140479184065152 False 30172
140479185936456 140479184065152 False 678
140479185966096 140479184065152 False 29168
140479184063752 140479184065152 False 48626
140479185936888 140479184065152 False 62443
140479184052336 140479184065152 False 10262
140479184061232 140479184065152 False 20831
140479185936888 140479184065152 False 62443
140479184057712 140479184065152 False 30650
140479185957880 140479184065152 False 15330
140479185936888 140479184065152 False 62443
140479185959760 140479184065152 False 6937
140479184061528 140479184065152 False 51067
140479184058728 140479184065152 False 23944
140479185944264 140479184065152 False 39191
140479184062568 140479184065152 False 3777
140479184063752 140479184065152 False 48626

Use is when checking for identity.

用于检查身份。

Ref: String comparison in Python: is vs. ==

参考:Python中的字符串比较:是与==

#6


0  

The is operator is used to compare the identities of the two objects So basically You're comparing whether the objects have the same identity, not whether they are equal

is运算符用于比较两个对象的身份所以基本上你要比较对象是否具有相同的身份,而不是它们是否相等

So if you print the id's of the objects involved using the id() function their id's are different so the is operator doesn't work in this case:

因此,如果使用id()函数打印所涉及对象的id,则它们的id不同,因此is运算符在这种情况下不起作用:

>>>print [(id(link),id(62443)) for link in links if link.submitter_id == 62443]
[(28741560, 21284824), (28860576, 21284824), (28860744, 21284824)]

Although just because two objects are similar there identities might not be the same

虽然仅仅因为两个对象相似,但身份可能不一样


Note: After an object is garbage collected, it's id is available to be reused. So the use of the is operator is actually somewhat discouraged

注意:对象被垃圾回收后,可以重用它的id。因此,实际上有人不鼓励使用is运算符

#1


9  

There's no answer to your question short of digging into details of the implementation of the specific version of Python you're using. Nothing is defined about whether a == b implies a is b when a and b are numbers. It's often true, and especially for "little integers", due to that CPython keeps a cache of little integer objects and usually (not always!) returns the same object for a given small integer value. But nothing about that is defined, guaranteed, or even always the same across releases.

除了深入研究您正在使用的特定Python版本的实现细节之外,您的问题没有答案。当a和b是数字时,没有定义a == b是否暗示a是b。这通常是正确的,特别是对于“小整数”,因为CPython保留了一些小整数对象的缓存,并且通常(并非总是!)为给定的小整数值返回相同的对象。但是没有任何关于它的定义,保证,甚至在各个版本中始终相同。

Thinking about memory addresses can be mildly helpful, since that's how id() is implemented in CPython. But other implementations use different implementations for id(). For example, I was told that id() was a major pain to implement in Jython (Python implemented in Java), since Java is free to move objects around in memory during garbage collection (CPython does not: in CPython an object always occupies the memory originally allocated for it, until the object becomes trash).

考虑内存地址可能会有一些帮助,因为这就是在CPython中实现id()的方式。但是其他实现对id()使用不同的实现。例如,我被告知id()是在Jython中实现的一个主要难题(用Java实现的Python),因为Java在垃圾收集期间可以*地在内存中移动对象(CPython没有:在CPython中,对象总是占用最初为它分配的内存,直到对象变为垃圾)。

The only intended - and supported - use for is is to check whether two names for objects in fact resolve to the very same object. For example, regardless of the type of b, after

唯一用于和支持的用途是检查对象的两个名称是否实际上解析为同一个对象。例如,不管b的类型如何

a = b

it must be the case that

一定是这样的

a is b

is True. And that's sometimes useful.

是真的。这有时很有用。

_sentinel = object() # create a unique object

def somefunc(optional=_sentinel):
    if optional is _sentinel:  # we know for sure nothing was passed
        ...

The other main use is for the handful of objects guaranteed to be singletons. None, True and False are examples of that, and indeed it's idiomatic to write:

另一个主要用途是保证为单身的少数对象。没有,是真是假的例子,实际上它写的是惯用的:

if a is None:

instead of:

if a == None:

The first way succeeds if and only if a is in fact bound to the the singleton None object, but the second way may succeed if a is of any type such that a.__eq__(None) returns True.

当且仅当a实际上绑定到单例None对象时,第一种方式成功,但如果a是任何类型,使得.__ eq __(None)返回True,则第二种方式可能成功。

Don't use is for numbers. That's insane ;-)

不要用于数字。那太疯狂了;-)

#2


5  

You are correct in that is checks identity, if the two variables are the same object, and that == is used to check equality, if the objects are equal. (What equal means is decided by the involved classes).

你是正确的是检查身份,如果两个变量是同一个对象,并且==用于检查相等性,如果对象是相等的。 (所涉及的等级决定了相同的手段)。

And you are correct that using is to check if two numbers are equal often works, because Python reuse numbers, so often when they are equal, they are also identical.

你是正确的,使用是检查两个数字是否相等通常是有效的,因为Python重用数字,所以通常当它们相等时,它们也是相同的。

But you do notice how that sounds. Should you check if two numbers are equal, by using the identity check? No, of course not. You should use the equality check to check if objects are equal. It's as simple as that.

但你确实注意到这听起来如何。你应该通过身份检查来检查两个号码是否相等吗?不,当然不。您应该使用相等性检查来检查对象是否相等。就这么简单。

That you often can use the identity check to check the equality of numbers is just a side-effect of Python reusing numbers, which it does to save memory, and which is an implementation detail.

您经常可以使用身份检查来检查数字的相等性只是Python重用数字的副作用,它可以节省内存,这是一个实现细节。

Besides, in Python 3 == 3.0, but 3 is not 3.0. So you should use == for that reason.

此外,在Python 3 == 3.0中,但3不是3.0。因此你应该使用==。

#3


1  

There are two parts to this question

这个问题分为两部分

  1. is does not checks for equality, it just checks for identity. Two objects have same identity iff they are same objects (with same identity i.e. id(a) == id(b))

    是不检查相等性,它只是检查身份。如果两个对象是相同的对象(具有相同的标识,即id(a)== id(b)),则它们具有相同的标识

    >>> a = 10
    >>> b = a
    >>> id(a), id(b)
    (30388628, 30388628)
    
  2. CPython as Implemented (may be for others) certain numbers range of integers within a certain limit, they are cached so even though they are different objects, yet they have the same identity

    CPython as Implemented(可能是为其他人)某些数字范围内的整数在一定限度内,它们被缓存,即使它们是不同的对象,但它们具有相同的身份

Thus

>>> a is 200
True
>>> a = 2000
>>> a is 2000
False

#4


0  

This is because is compares identities:

这是因为比较身份:

>>> a = 10
>>> id(a)
30967348
>>> id(10)
30967348
>>> a is 10
True
>>> a += 1
>>> a
11
>>> id(a)
30967336
>>> id(11)
30967336
>>> a is 11
True
>>> a = 106657.334
>>> id(a)
44817088
>>> id(106657.334)
31000752
>>> a is 106657.334
False
>>> a == 106657.334
True

#5


0  

is used to compare identity.

用于比较身份。

In [26]: a = 3

In [27]: a is 3
Out[27]: True

In [28]: id(a)
Out[28]: 140479182211448

In [29]: id(3)
Out[29]: 140479182211448

Extending same to the above example.

将其扩展到上面的例子。

In [32]: for link in links:
    print id(link.submitter_id), id(62443), id(link.submitter_id) == id(62443), link.submitter_id

....:

140479184066728 140479184065152 False 60398
140479184066872 140479184065152 False 60254
140479184065688 140479184065152 False 62945
140479184064984 140479184065152 False 6084
140479184064648 140479184065152 False 30305
140479184063416 140479184065152 False 59008
140479184063608 140479184065152 False 8712
140479184063752 140479184065152 False 48626
140479184064352 140479184065152 False 30172
140479185936456 140479184065152 False 678
140479185966096 140479184065152 False 29168
140479184063752 140479184065152 False 48626
140479185936888 140479184065152 False 62443
140479184052336 140479184065152 False 10262
140479184061232 140479184065152 False 20831
140479185936888 140479184065152 False 62443
140479184057712 140479184065152 False 30650
140479185957880 140479184065152 False 15330
140479185936888 140479184065152 False 62443
140479185959760 140479184065152 False 6937
140479184061528 140479184065152 False 51067
140479184058728 140479184065152 False 23944
140479185944264 140479184065152 False 39191
140479184062568 140479184065152 False 3777
140479184063752 140479184065152 False 48626

Use is when checking for identity.

用于检查身份。

Ref: String comparison in Python: is vs. ==

参考:Python中的字符串比较:是与==

#6


0  

The is operator is used to compare the identities of the two objects So basically You're comparing whether the objects have the same identity, not whether they are equal

is运算符用于比较两个对象的身份所以基本上你要比较对象是否具有相同的身份,而不是它们是否相等

So if you print the id's of the objects involved using the id() function their id's are different so the is operator doesn't work in this case:

因此,如果使用id()函数打印所涉及对象的id,则它们的id不同,因此is运算符在这种情况下不起作用:

>>>print [(id(link),id(62443)) for link in links if link.submitter_id == 62443]
[(28741560, 21284824), (28860576, 21284824), (28860744, 21284824)]

Although just because two objects are similar there identities might not be the same

虽然仅仅因为两个对象相似,但身份可能不一样


Note: After an object is garbage collected, it's id is available to be reused. So the use of the is operator is actually somewhat discouraged

注意:对象被垃圾回收后,可以重用它的id。因此,实际上有人不鼓励使用is运算符