Compare an object with an empty tuple with the 'is' operator in Python 2.x

I'm used to seeing if obj is None: in Python, and I recently met if obj is (): Since tuples do not change, the Python interpreter sounds like a reasonable internal optimization to have an empty tuple, so it allows you to use is instead of requiring == . But is it guaranteed somewhere? What version of the interpreter?

[edit] The question matters because if () is not single, and there is a way to create an empty tuple with a different address, then using is {} is an error. If this is guaranteed only with Python 2.x with x> 0, then it is important to know the value of x if you need to ensure backward compatibility of your code. It is also important to know if this could break your code when using pypy / jython / ironpython ...

+8
python
source share
4 answers

From Python 2 docs and Python 3 docs :

... two occurrences of an empty tuple may or may not yield the same object.

In other words, you cannot rely on () is () to evaluate as true.

+11
source share

Use the id () method to get the internal identifier ():

 >>> id(()) 140180995895376 >>> empty_tuple = () >>> id(empty_tuple) 140180995895376 # same as the id of () >>> from copy import copy >>> id(copy(empty_tuple)) 140180995895376 # still the same as the id of () 

It seems that () is effectively stored as a single element in python (at least in python> 2.6).

There is the same behavior for the empty string variable "" .

0
source share

This is not a guaranteed implementation detail for current versions of CPython, so you will not have to rely on it in other Python implementations, including Jython, IronPython, PyPy, and potentially future versions of CPython.

Using is compared to a large list looks like about 0.04 m on my system:

 $ python -m timeit -s "x = range(10000)" "x is ()" 10000000 loops, best of 3: 0.0401 usec per loop $ python -m timeit -s "x = range(10000)" "x == ()" 10000000 loops, best of 3: 0.0844 usec per loop 

Of course, this could be significantly worse if you are comparing something with the __eq__() custom method:

 $ python -m timeit -s $'import time\nclass X(object):\n def __eq__(self, other): return time.sleep(1)\nx = X()' "x == ()" 10 loops, best of 3: 1e+03 msec per loop 

However, if this difference in performance is important, I think it will indicate a design problem.

0
source share

This is not about optimization. This is about comparing objects. Python "is" is used to verify the identity of the object, and then the operator "==" is not required to compare the empty tuple "()". In fact, everything in python can be compared to "is".

 >>> obj = () >>> obj is () True >>> isinstance(obj, tuple) True >>> obj is tuple False >>> type(obj) is tuple True >>> type(()) <type 'tuple'> >>> type(tuple) <type 'type'> >>> tuple == type(()) # value comparison with == True 

The same for any other value:

 >>> 333 is int False >>> type(333) is int True >>> isinstance(333, int) True 
0
source share

All Articles