float(1.0) is float(1.0) #True
float(1) is float(1) #False
我在这里将float()奇数与对象创建顺序隔离开,因为
x1 = float(1)
x2 = float(1)
x1 is x2 #False
id(x1) == id(x2) #False
y1 = float(1.0)
y2 = float(1.0)
y1 is y2 #True
id(y1) == id(y2) #True
注意:我已经检查了浮子的精度,这不是发生这种情况的原因。
我希望了解Python为什么以及如何决定创建float对象。 为什么float(1.0)指向同一对象,而float(1)指向两个不同的对象却又创建了两次?
此外,供进一步参考:
float(1) is float(1) #False
id(float(1)) == id(float(1)) #True
float(1.0) is float(1.0) #True
id(float(1.0)) == id(float(1.0)) #True
答案 0 :(得分:6)
>>> float(1.0) is float(1.0)
True
那是因为float
返回对象本身,因为它已经是float
(与字符串BTW Should I avoid converting to a string if a value is already a string?相同)。
检查source code进行确认(添加注释):
static PyObject *
float_float(PyObject *v)
{
if (PyFloat_CheckExact(v)) // if v is already a float, just increase reference and return the same object
Py_INCREF(v);
else
// else create a new float object using the input value
v = PyFloat_FromDouble(((PyFloatObject *)v)->ob_fval);
return v;
}
编译时可能会共享原义1.0
上的引用(这是实现的定义,这是我能想到的唯一解释,Dunes answer会更好地解释它),因此它与{ {1}}。
1.0 is 1.0
Python必须为每一侧创建浮点对象,因此有所不同。没有像整数这样的浮点数实习。
最后一个有趣的部分:
>>> float(1) is float(1)
False
因为>>> id(float(1)) == id(float(2))
True
对象是在调用float
之后被垃圾回收的,所以即使字面值是不同的,id也被重用。如以上示例所示(在Unnamed Python objects have the same id或Why is the id of a Python class not unique when called quickly?中公开)。
答案 1 :(得分:2)
1.0
是float对象的文字语法,因此解释器必须创建一个float对象,然后可以将其传递给float
。由于浮点数是不可变的,因此float
函数可以不变地返回对象。另一方面,1
是整数的文字语法。这样,float
函数必须创建一个新的float对象。在同一代码块中,解释器有时(并非总是)能够识别出不可变对象的两个文字是相同的,然后它就可以缓存该对象并重用于其他引用。这是内部内存优化,因此不应依赖。
因此:
def f():
x = 1.0
y = float(1.0)
z = float(x)
assert x is y # x and y are the same object
assert x is z # z is also the same as both x and y
f()
但是:
def f():
return 1.0
def g():
return 1.0
assert f() is not g() # The interpreter was not able to detect it could reuse the same object
长话短说,有时python中等于可能的数字也是完全相同的对象,但这并不能保证。