Why (0-6) Is -6 = False

Why (0-6) is -6 = False?

All integers from -5 to 256 inclusive are cached as global objects sharing the same address with CPython, thus the is test passes.

This artifact is explained in detail in http://www.laurentluce.com/posts/python-integer-objects-implementation/, and we could check the current source code in http://hg.python.org/cpython/file/tip/Objects/longobject.c.

A specific structure is used to refer small integers and share them so access is fast. It is an array of 262 pointers to integer objects. Those integer objects are allocated during initialization in a block of integer objects we saw above. The small integers range is from -5 to 256. Many Python programs spend a lot of time using integers in that range so this is a smart decision.

This is only an implementation detail of CPython and you shouldn't rely on this. For instance, PyPy implemented the id of integer to return itself, so (0-6) is -6 is always true even if they are "different objects" internally; it also allows you to configure whether to enable this integer caching, and even set the lower and upper bounds. But in general, objects retrieved from different origins will not be identical. If you want to compare equality, just use ==.

Why and how does the Python interpreter remember literal objects

There's a range of small numbers that are kept as singletons within Python; any reference will always return the same object and they will never be garbage collected.

>>> for x,y in enumerate(range(1000)):
if x is not y:
print x,y
break

257 257

What does 'is' operator do in Python?

You missed that is not is an operator too.

Without is, the regular not operator returns a boolean:

>>> not None
True

not None is thus the inverse boolean 'value' of None. In a boolean context None is false:

>>> bool(None)
False

so not None is boolean True.

Both None and True are objects too, and both have a memory address (the value id() returns for the CPython implementation of Python):

>>> id(True)
4440103488
>>> id(not None)
4440103488
>>> id(None)
4440184448

is tests if two references are pointing to the same object; if something is the same object, it'll have the same id() as well. is returns a boolean value, True or False.

is not is the inverse of the is operator. It is the equivalent of not (op1 is op2), in one operator. It should not be read as op1 is (not op2) here:

>>> 1 is not None     # is 1 a different object from None?
True
>>> 1 is (not None) # is 1 the same object as True?
False

Getting weird results while subtraction manipulation in python

Don't use is for equality testing - it's the identity operator, and two equal objects are not necessarily identical (i. e. residing under the same address in your computer's memory). Some small integers may be cached and reused but not all of them which is why you're seeing different results here.

Additionally, this behavior is implementation-dependent, so you can't rely on this always being the case.

How to tell when 2 variables with same value will have different identities?

The small integers are getting interned.

Short ints with small values (typically between -1 and 99
inclusive) are "interned" -- whenever a result has such a value,
an existing short int with the same value is returned. This is
not done for long ints with the same values.

Further,

But code may exist that uses 'is' for comparisons of short ints and
happens to work because of this interning. Such code may fail
if used with long ints.)

However, this isn't behavior that should be relied upon as it is implementation-specific. It isn't going to work for larger integers and interning isn't guaranteed, so you shouldn't be using is here.
Other than integers, strings may also be interned.

(PEP-0237)



Related Topics



Leave a reply



Submit