negative numbers are not equal...

castironpi castironpi at gmail.com
Fri Aug 15 13:19:21 EDT 2008


On Aug 15, 8:56 am, Dan Lenski <dlen... at gmail.com> wrote:
> On Thu, 14 Aug 2008 17:18:55 -0300, ariel ledesma wrote:
> > hello guys
>
> > i just ran into this when comparing negative numbers, they start
> > returning False from -6 down, but only when comparing with 'is'
>
> >  >>> m = -5
> >  >>> a = -5
> >  >>> m is a
> > True
> >  >>> m = -6
> >  >>> a = -6
> >  >>> m is a
> > False
> >  >>> m == a
> > True
>
> > i read that 'is' compares if they are really the same object, but i
> > don't that's it because then why does -5 return True? of course i could
> > only use == to compare, but still, what am i missing here? thanks in
> > advance
>
> They also return False for positive numbers > 256.  Try this:
>  >>> print [x for x in range(-10,260) if x is not x+1-1]
> [-10, -9, -8, -7, -6, 257, 258, 259]
>
> There is a good explanation for this: the "is" operator checks for object
> identity, not equality.  Basically "a is m" asks, does the variable name
> "a" reference the same memory location as the variable name "m"?
>
> For integers in the range of -5<=x<=256, Python pre-caches all of these
> values, and whenever a variable takes on one of those values, it uses the
> cached value.  This is an optimization: it prevents the need to allocate
> a new Python object for these very very common small integer values.
>
> For integer literals outside this range, a new Python object gets created
> when they are assigned to variables, so a=500 followed by m=500 will
> create new objects.
>
> The "is" operator just shows the effect of this caching.  It's
> unimportant for real code since you never care whether two numeric
> variables refer to the same object (only important for complex data
> structures where their storage may overlap)... only whether they are
> equal or not.
>
> Dan Lenski
>
> (PS- The small integer pre-caching is described somewhere in the C API
> docs.)

It would be nice to put together a really canonical case of the use of
the 'is' comparison.  FTSOA for the sake of argument, when do you use
it?  Why is it even in the language?

If you're iterating over a list,

flagA= object()
flagB= object()
flagC= -10
listA= [ objectA, objectB, flagA, objectC, flagB, -10, objectD ]
flags= [ listA, listB, listC ]
for iA in listA:
   for flag in flags:
      if iA is flag:
         handle( iA )

This case actually misses handleC().  The solution is that the
function that is returning '-10' cannot return -10, it has to return
flagC.  This can cause difficulties in cases when you're doing
operations on flags.  Worse, if flagC is nested somewhere, say
moduleA.classB.flagC, you still have to work with that, not its value.



More information about the Python-list mailing list