Python 标准类型比较
请看下面的例子:
>>> a=1
>>> b=1
>>> a is b
True
>>> c=1.0
>>> d=1.0
>>> c is d
False
是不是非常奇怪,下面解释原因:
上面的例子a,b指向了同一个整形对象,但是c,d却不是只想同一对象,原因在于
整形和字符串对象是不可变对象,Python高效的缓存这些整形和字符串,Python应用程序中经常会用到这些小型整数,因此Python会缓存这些整数
源码如下:
#include "Python.h" #include "longintrepr.h" #include <float.h> #include <ctype.h> #include <stddef.h> #include "clinic/longobject.c.h" /*[clinic input] class int "PyObject *" "&PyLong_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/ #ifndef NSMALLPOSINTS #define NSMALLPOSINTS 257 #endif #ifndef NSMALLNEGINTS #define NSMALLNEGINTS 5 #endif _Py_IDENTIFIER(little); _Py_IDENTIFIER(big); /* convert a PyLong of size 1, 0 or -1 to an sdigit */ #define MEDIUM_VALUE(x) (assert(-1 <= Py_SIZE(x) && Py_SIZE(x) <= 1), \ Py_SIZE(x) < 0 ? -(sdigit)(x)->ob_digit[0] : \ (Py_SIZE(x) == 0 ? (sdigit)0 : \ (sdigit)(x)->ob_digit[0])) PyObject *_PyLong_Zero = NULL; PyObject *_PyLong_One = NULL; /* Create a new int object from a C long int */ PyObject * PyLong_FromLong(long ival) { PyLongObject *v; unsigned long abs_ival; unsigned long t; /* unsigned so >> doesn't propagate sign bit */ int ndigits = 0; int sign; CHECK_SMALL_INT(ival); if (ival < 0) { /* negate: can't write this as abs_ival = -ival since that invokes undefined behaviour when ival is LONG_MIN */ abs_ival = 0U-(unsigned long)ival; sign = -1; } else { abs_ival = (unsigned long)ival; sign = ival == 0 ? 0 : 1; } /* Fast path for single-digit ints */ if (!(abs_ival >> PyLong_SHIFT)) { v = _PyLong_New(1); if (v) { Py_SIZE(v) = sign; v->ob_digit[0] = Py_SAFE_DOWNCAST( abs_ival, unsigned long, digit); } return (PyObject*)v; } #if PyLong_SHIFT==15 /* 2 digits */ if (!(abs_ival >> 2*PyLong_SHIFT)) { v = _PyLong_New(2); if (v) { Py_SIZE(v) = 2*sign; v->ob_digit[0] = Py_SAFE_DOWNCAST( abs_ival & PyLong_MASK, unsigned long, digit); v->ob_digit[1] = Py_SAFE_DOWNCAST( abs_ival >> PyLong_SHIFT, unsigned long, digit); } return (PyObject*)v; } #endif /* Larger numbers: loop to determine number of digits */ t = abs_ival; while (t) { ++ndigits; t >>= PyLong_SHIFT; } v = _PyLong_New(ndigits); if (v != NULL) { digit *p = v->ob_digit; Py_SIZE(v) = ndigits*sign; t = abs_ival; while (t) { *p++ = Py_SAFE_DOWNCAST( t & PyLong_MASK, unsigned long, digit); t >>= PyLong_SHIFT; } } return (PyObject *)v; }
(范围在(-5,257)),再有新的引用时,并不创建新的对象。