Python values actually aren't equivalent [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python “is” operator behaves unexpectedly with integers
I'm learning Python, and am curious as to why:
x = 500
x is 500
returns False, but:
y = 100
y is 100
returns True?

Python reuses small integers. That is, all 1s (for example) are the same 1 object. The range is -5 to 255, if I remember correctly, though this is a CPython implementation detail that should not be relied upon. I am pretty sure Jython and IronPython, for example, handle this differently.
The reason this works out fine is that ints are immutable. That is, you can't change a 4 to a 5 in-place. if a has a value of 4, a = 5 is actually pointing a to a different object, not changing the value a contains. Python doesn't share any mutable types (such as lists) where unexpectedly having multiple references to the same object might cause problems.
You should use == for comparing most things. is is for checking to see whether two references point to the same object; it is roughly equivalent to id(x) == id(y).

is tests for identity - x is y asks if they are the same object, not if they are simply 'equivalent'. So you also have, eg:
>>> x = []
>>> y = []
>>> z = x
>>> x is y
False
>>> x is z
True
For equivalence, you want to test equality:
>>> x = 500
>>> x == 500
True
Python (or, at least, cpython - the major implementation) does some optimisations so that certain immutable objects only exist once throughout the lifetime of the interpreter. So, every 5 throughout your program will be the same integer object. The same thing happens with string literals, for example.

"is" compare objects IDs and "==" will compare object values. So, if you need to compare values, go with "==" and if you whant to compare objects, go with "is".
As in Python everything is an object, is compares objects IDs, it's faster, but some times unpredictable. You need to be very sure of what you are doing to use "is" for simple comparsion.
About the situation above, I found here: http://docs.python.org/c-api/int.html the following remark:
The current implementation keeps an array of integer objects for all
integers between -5 and 256, when you create an int in that range you
actually just get back a reference to the existing object. So it
should be possible to change the value of 1. I suspect the behaviour
of Python in this case is undefined. :-)
So, you can do the following test and see this behaviour:
>>> a = 256
>>> id(a)
19707932
>>> id(256)
19707932
>>> a = 257
>>> id(a)
26286076
>>> id(257)
26286064
So, for integers above 256, "is" will not work. Be careful using "is" for comparsion.

Related

Checking Objects and Values using Is Operator in Python [duplicate]

This question already has answers here:
Understanding the "is" operator [duplicate]
(11 answers)
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 1 year ago.
Why is this:
x = str(input("Enter a string: ")) #input "cat"
y = str(input("Enter another string: ")) #input "cat"
print(x is y) #Outputs False
Not the same as this:
x = "cat"
y = "cat"
print(x is y) #Outputs True
From this Real Python article:
The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory. In the vast majority of cases, this means you should use the equality operators == and !=, except when you’re comparing to None.
>>> x = None
>>> y = None
>>> id(x); id(y)
4389651888
4389651888
>>> x is y
True
== calls the __eq__ method of an object, is checks whether the id() of two objects is equal (memory address).
The rest of the article I linked is really informative; it talks about how Python will give the same id to small integers by default, and that you can use the sys.intern() method to ensure string variables point to the same object in memory as well.
The is operator in python is used to check if two objects point to the same memory location.
In the second case, when python runs, for optimization purposes both x and y point to the same memory location. However, in the first case, x and y are not defined until the user inputs a value during run time. So, they're both allocated memory in different locations.

Python: if elif loop [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 9 years ago.
I noticed a Python script I was writing was acting squirrelly, and traced it to an infinite loop, where the loop condition was while line is not ''. Running through it in the debugger, it turned out that line was in fact ''. When I changed it to !='' rather than is not '', it worked fine.
Also, is it generally considered better to just use '==' by default, even when comparing int or Boolean values? I've always liked to use 'is' because I find it more aesthetically pleasing and pythonic (which is how I fell into this trap...), but I wonder if it's intended to just be reserved for when you care about finding two objects with the same id.
For all built-in Python objects (like
strings, lists, dicts, functions,
etc.), if x is y, then x==y is also
True.
Not always. NaN is a counterexample. But usually, identity (is) implies equality (==). The converse is not true: Two distinct objects can have the same value.
Also, is it generally considered better to just use '==' by default, even
when comparing int or Boolean values?
You use == when comparing values and is when comparing identities.
When comparing ints (or immutable types in general), you pretty much always want the former. There's an optimization that allows small integers to be compared with is, but don't rely on it.
For boolean values, you shouldn't be doing comparisons at all. Instead of:
if x == True:
# do something
write:
if x:
# do something
For comparing against None, is None is preferred over == None.
I've always liked to use 'is' because
I find it more aesthetically pleasing
and pythonic (which is how I fell into
this trap...), but I wonder if it's
intended to just be reserved for when
you care about finding two objects
with the same id.
Yes, that's exactly what it's for.
I would like to show a little example on how is and == are involved in immutable types. Try that:
a = 19998989890
b = 19998989889 +1
>>> a is b
False
>>> a == b
True
is compares two objects in memory, == compares their values. For example, you can see that small integers are cached by Python:
c = 1
b = 1
>>> b is c
True
You should use == when comparing values and is when comparing identities. (Also, from an English point of view, "equals" is different from "is".)
The logic is not flawed. The statement
if x is y then x==y is also True
should never be read to mean
if x==y then x is y
It is a logical error on the part of the reader to assume that the converse of a logic statement is true. See http://en.wikipedia.org/wiki/Converse_(logic)
See This question
Your logic in reading
For all built-in Python objects (like
strings, lists, dicts, functions,
etc.), if x is y, then x==y is also
True.
is slightly flawed.
If is applies then == will be True, but it does NOT apply in reverse. == may yield True while is yields False.

Assignment of variables in Python [duplicate]

This question already has answers here:
identifying objects, why does the returned value from id(...) change?
(7 answers)
Python integer caching
(2 answers)
Closed 6 years ago.
In Python I created integer and list objects as follows:
a = 10
b = 10
x = []
y = []
Then I get the following results while comparing the id of a and b, and the id of x and y
id(a)==id(b) returns True
id(x)==id(y) returns False
Somewhere I read that assignment in Python never copies data. My question is why x and y do not have the same id?
You must know that python integers ar cached and inmutable, that means that both a and b are labeling the same 10. Lists are objects and they are allocated separetly, thats why their ids are diferent from the beggining
Lists are mutable, if the same object was used, when you add an item to one of the list, you'd see the change on the other one as well.
Identity of integers is implementation dependent, and it is usually valid only for small numbers; good reading here.
By the way, == is the equality operator. A shortest (and cleaner) way for id(a)==id(b) is to use the identity operator is. In your case: a is b.
x = [] is a shorthand for instantiating a new list, which means a new object with a new object ID. Even though x and y are assigned as empty lists, they are simply references to memory locations allocated for the respective lists. If id(x) == id(y) then x and y would share the same object ID, which would effectively mean they share a memory location, or are references to the same object (so any changes made to one would apply to the other).
On the other hand, id(a) == id(b) because they are both integers, which are primitive data types.

Different storage position of equal strings with special characters [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 8 years ago.
I am new at python and I'm currently exploring some of its core functionalities.
Could you explain me why the following example always return false in case of a string with special characters:
>>> a="x"
>>> b="x"
>>> a is b
True
>>> a="xxx"
>>> b="xxx"
>>> a is b
True
>>> a="xü"
>>> b="xü"
>>> a is b
False
>>> a="ü"
>>> b="ü"
>>> a is b
True
>>> #strange: with one special character it works as expected
I understand that the storage positions are different for strings with special characters on each assignment, I already checked it with the id() function but for which reason python handles strings in this unconsistent way?
Python (the reference implementation at least) has a cache for small integers and strings. I guess unicode strings outside the ASCII range are bigger than the cache threshold (internally unicode is stored using 16 or 32 bit wide characters, UCS-2 or UCS-4) and so they are not cached.
[edit]
Found a more complete answer at: About the changing id of a Python immutable string
Se also: http://www.laurentluce.com/posts/python-string-objects-implementation/
With is you're not testing equality between strings, you're testing equality between objects which is resolved through pointers. So your code:
>>> a="x"
>>> b="x"
>>> a is b
True
is not asking "are a and b the same character?", its asking "are a and b the same object?". Since there's a small object cache (for small integers and one byte strings, as has been said before), the answer is "yes, both variables refer to the same object in memory, the x character small object".
When you work with an object that is not eligible for the cache, as in:
>>> a="xü"
>>> b="xü"
>>> a is b
False
what is going on is that a and b now refer to different objects in memory, so the is operator resolves to false (a and b do not point to the same object!).
If the idea is comparing strings, you should use the == operator instead of is.

Comparing strings using '==' and 'is' [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Types for which “is” keyword may be equivalent to equality operator in Python
Python “is” operator behaves unexpectedly with integers
Hi.
I have a question which perhaps might enlighten me on more than what I am asking.
Consider this:
>>> x = 'Hello'
>>> y = 'Hello'
>>> x == y
True
>>> x is y
True
I have always used the comparison operator. Also I read that is compares the memory address and hence in this case, returns True
So my question is, is this another way to compare variables in Python? If yes, then why is this not used?
Also I noticed that in C++, if the variables have the same value, their memory addresses are different.
{ int x = 40; int y = 40; cout << &x, &y; }
0xbfe89638, 0xbfe89634
What is the reason for Python having the same memory addresses?
This is an implementation detail and absolutely not to be relied upon. is compares identities, not values. Short strings are interned, so they map to the same memory address, but this doesn't mean you should compare them with is. Stick to ==.
There are two ways to check for equality in Python: == and is. == will check the value, while is will check the identity. In almost every case, if is is true, then == must be true.
Sometimes, Python (specifically, CPython) will optimize values together so that they have the same identity. This is especially true for short strings. Python realizes that 'Hello' is the same as 'Hello' and since strings are immutable, they become the same through string interning / string pooling.
See a related question: Python: Why does ("hello" is "hello") evaluate as True?
This is because of a Python feature called String interning which is a method of storing only one copy of each distinct string value.
In Python both strings and integers are immutable therefore you can cache them. Integers in the range of ´-5´ to ´256´ and small strings(don't know the exact size atm) get cached, therefore they are the same object. x and y are only names that refer to these objects.
Also == compares for equals values, while is compares for object identity. None True and False are global objects, for example you can rebind False to True.
The following shows that not every thing is being cached:
x = 'Test' * 2000
y = 'Test' * 2000
>>> x == y
True
>>> x is y
False
>>> x = 10000000000000
>>> y = 10000000000000
>>> x == y
True
>>> x is y
False
In Python, variables are just names that point to some object (and they can point to the same object). In C++, variables also define the actual memory that is reserved for them; this is why they have distinct memory addresses.
About Python string interning and differences between the two comparison operators, see carl's response.

Categories