порядок создания идентификатора объекта float () - PullRequest
0 голосов
/ 12 декабря 2018
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 (1.0) указывает на один и тот же объект, в то время как float (1) указывает на 2 разных объекта, когда оба создаются дважды?

Кроме того, для дальнейшей справки:

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

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

1.0 - это буквальный синтаксис для объекта с плавающей точкой, поэтому интерпретатор должен создать объект с плавающей точкой, который он может передать float.Поскольку числа с плавающей точкой неизменны, функция float может просто вернуть объект без изменений.С другой стороны, 1 - это буквальный синтаксис для целого числа.Таким образом, функция 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, которыеравны , может также быть точно таким же объектом, но это не гарантируется.

0 голосов
/ 12 декабря 2018
>>> float(1.0) is float(1.0)
True

Это потому, что float возвращает сам объект, потому что он уже float (то же самое для строк BTW Следует ли мне избегать преобразования в строку, если значение уже является строкой? ).

Проверка исходного кода для подтверждения (с добавленными комментариями):

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, вероятно, используется совместно при компиляции (это определяется реализациейи это единственное объяснение, которое я могу придумать, ответ Дюны объясняет это гораздо лучше), так что это то же самое, что 1.0 is 1.0.

>>> float(1) is float(1)
False

Python должен создавать объекты с плавающей запятойдля каждой стороны, так что это разные.Не существует интернирования с плавающей запятой, например целых чисел.

И последняя забавная часть:

>>> id(float(1)) == id(float(2))
True

, потому что объект float собирается мусором после вызова id, поэтому id повторно , даже если литеральные значения отличаются , как показано в примере выше (как показано в Безымянный объект Python имеет тот же идентификатор или ПочемуИдентификатор класса Python не уникален при быстром вызове? ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...