Как работает интерпретатор Python при динамической типизации?

Я прочитал этот вопрос, но он не дал мне однозначного ответа: как интерпретатор Python ищет типы?

Как интерпретатор Python узнает тип переменной? Я не смотрю, как получить тип. Я здесь смотрю на то, что происходит за сценой. В приведенном ниже примере, как он связывает класс int или строку с моей переменной.

Откуда он знает, что это int:

>>> i = 123
>>> type(i) 
<class 'int'>

или эта строка:

>>> i = "123"
>>> type(i)
<class 'str'>

3 ответа

Решение

как это связывает класс int или строку с моей переменной

Python нет. Переменные не имеют типа. Только объект, на который ссылается переменная, имеет тип. Переменные - это просто имена, указывающие на объекты.

Например, следующее также показывает тип объекта, но переменная не используется:

>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>

Когда вы используете type(variable), variable часть выражения просто возвращает объект, на который ссылается имя, передавая объект type() функция. Когда используешь 1 или же 'foobar'выражение является литералом, создающим объект, который затем передается type() функция.

Объекты Python - это просто структуры данных в памяти интерпретатора; в CPython C используются структуры. Переменные - это просто ссылки (указатели) на эти структуры. Базовая структура типов в CPython называется PyObjectи эта структура имеетob_type слот, который говорит Python, что типа что-то. Типы - это просто C-структуры.

Если вы хотите следовать исходному коду CPython, вы должны начать сbltinmodule.c исходный кодtype является встроенным именем), который определяет type как PyType_Type структура. Вызовтипа(type это тоже тип) вызывает ихtp_new функция иPyType_Type определяет это как type_new функция Эта функция обрабатывает вызовы с одним аргументом следующим образом:

/* Special case: type(x) should return x->ob_type */
{
    const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
    const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);

    if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
        PyObject *x = PyTuple_GET_ITEM(args, 0);
        Py_INCREF(Py_TYPE(x));
        return (PyObject *) Py_TYPE(x);
    }

Вот x это PyObject объект, который вы передали; обратите внимание, не переменная, а объект! Так что для вашего 1 целочисленный объект или 'foobar' строковый объект, Py_TYPE() результат макроса возвращается. Py_TYPE это макрос, который просто возвращает ob_type значение любого PyObject структура.

Итак, теперь у вас есть тип объекта для 1 или же 'foobar'; как ты видишь <class 'int'> или же <class 'str'> в вашей сессии переводчика? Интерактивный интерпретатор Python автоматически использует repr() функция на любое выражение результатов. В структуре C для PyType_Type определения PyType_Type структура включена, так что все слоты для этого типа доступны напрямую; Я опущу здесь, как именно это работает. Для объектов типа, используя repr() означает type_reprвызывается функция, которая возвращает это:

rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);

Итак, в конце концов, type(1) получает ->ob_type слот, (который оказывается PyLong_Type структура в Python 3, длинная история), и эта структура имеет tp_name слот установлен на"int",

TL; DR: переменные Python не имеют типа, они просто указатели на объекты. У объектов есть типы, и интерпретатор Python будет следовать серии косвенных ссылок, чтобы получить имя типа для печати, если вы повторяете объект в вашем интерпретаторе.

Переменные Python не имеют типа, они просто ссылки на объекты. Размер ссылки одинаков независимо от того, на что он ссылается. В реализации CPython это указатель, и у него есть тип, это указатель на объект Python: PyObject *, Указатель одного типа независимо от класса объекта. Объекты, с другой стороны, знают, к какому классу они принадлежат.

Утверждалось, что в Python нет переменных, только имена, хотя для большинства людей это слишком далеко.

Ссылки в реализации CPython имеют идентификатор (идентификатор), который фактически является виртуальным адресом. Детальность и ценность этого адреса не заслуживают внимания - он может (и, вероятно, будет) изменяться между версиями и не предназначен для использования для чего-либо, кроме уникального номера, идентифицирующего объект. Тем не менее он может предоставить интересные указатели (простите за каламбур) на то, что происходит:

>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264

Обратите внимание, что идентификатор (адрес) x а также y одинаковы - они ссылаются на один и тот же объект, int со значением 42. Итак, что происходит, когда мы меняем x делает y изменить также?

>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264

К счастью, нет. Сейчас x просто ссылается на новый объект класса str со значением "Hello".

Когда мы:

>>> id(y)
4297539264
>>> y = 37
>>> id(y)
4297539104 

Идентификатор y изменилось! Это потому, что теперь он ссылается на другой объект. int s являются неизменными, поэтому назначение y = 37 не изменил исходный объект (42) он создал новый. У объекта со значением 42 счетчик ссылок уменьшен и теперь (теоретически) может быть удален. На практике это, вероятно, останется в памяти по соображениям эффективности, но это деталь реализации.

Тем не мение:

>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
4324804808
>>> id(b)
4324804808
>>> a[0] = 99
>>> b
[99, 2, 3, 4]

Так что меняя список a изменился b! Это потому, что списки изменчивы, они могут меняться. Назначение b = a только скопировал ссылку, а не список. Смотрите копию в стандартной библиотеке.

Понятие "тип" переменной "реализуется" с использованием объектов определенного класса.

Так в

a=float()

объект типа floatкак определено классом float возвращается float(), Python знает, что это за тип, потому что так работают объекты: вы знаете, какой это тип. a сейчас float объект со значением 0.0.

Со встроенными, это то же самое, просто у них есть краткая информация для их объявления.

i=123

такой же как

i=int(123)

int() возвращает объект класса integer со значением 123.

так же

i="123"

такой же как

i=str("123")

str("123") возвращает объект класса str со значением "123"

Другие вопросы по тегам