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

时间:2013-12-19 05:52:14

标签: python integer

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

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

每当我将某些内容与数字进行比较时,我习惯使用is。但是is在下面的程序中不起作用:

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()

当我在is这样的查询函数中使用[link for link in links if link.submitter_id is 62443]时,我会得到一个空列表。但如果我使用==,它就可以正常工作。

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

编辑:是的。我承认这个问题是重复的,应该关闭。但它与first post而不是the second重复。在发布之前我不知道这个问题。

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

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

6 个答案:

答案 0 :(得分:9)

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

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

is的唯一预期和支持用途是检查对象的两个名称是否实际上解析为同一个对象。例如,无论b的类型如何,在

之后
a = b

必须是

的情况
a is b

True。这有时很有用。

_sentinel = object() # create a unique object

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

另一个主要用途是少数对象保证是单身。 NoneTrueFalse就是其中的一个例子,而且写作确实是惯用的:

if a is None:

而不是:

if a == None:

当且仅当a实际上绑定到单个None对象时,第一种方式成功,但如果a属于任何类型a.__eq__(None),则第二种方式可能成功{ {1}}返回True

不要将is用于数字。这太疯狂了; - )

答案 1 :(得分:5)

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

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

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

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

此外,在Python is中,但是3 == 3.0。因此,您应该使用3 is not 3.0

答案 2 :(得分:1)

这个问题分为两部分

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

    ,则它们具有相同的标识
    >>> a = 10
    >>> b = a
    >>> id(a), id(b)
    (30388628, 30388628)
    
  2. CPython as Implemented(可能适用于其他人)某些数字范围的整数在一定范围内,它们被缓存,即使它们是不同的对象,但它们具有相同的身份

  3. 因此

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

答案 3 :(得分:0)

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

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

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

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


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

答案 4 :(得分:0)

这是因为is比较了身份:

>>> 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用于比较身份。

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

将其扩展到上面的例子。

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

检查身份时使用is

参考:String comparison in Python: is vs. ==

相关问题