В Python все переменные - пустые указатели? - PullRequest
0 голосов
/ 09 мая 2018

За прошедшие годы я прочитал несколько постов, в которых переменные Python объяснялись как «у Python есть имена, у других языков есть переменные» или как «объекты, теги и блоки»

Мне всегда не нравились подобные объяснения, поскольку они требовали новых мысленных образов и, на мой взгляд, пытаются переопределить общую терминологию. (Возможно, в Python тоже есть переменные, а в других языках тоже есть имена.)

Поскольку я когда-либо занимался только правильным программированием на Python, я знал только его поведение, поэтому эти обсуждения не сильно повлияли на меня.

Тем не менее, я хотел бы знать, правильно ли мое следующее понимание этой темы, прежде чем защищать его в обсуждениях с другими:

Все переменные Python являются указателями

При написании этого вопроса я заметил, что подобный вопрос задавался ранее, и все в этом потоке, включая OP, пришли к выводу, что переменные Python являются , а не указателями (и вместо этого в ответах использовались приведенные выше объяснения), поскольку

i = 5
j = i
j = 3
print(i)

приводит к 5. Однако для меня этот результат имеет смысл. В моем понимании это переводится как

void *i;
void *j;

int temp1 = 5; %RHS of line 1 above
i = &temp1; %LHS of line 1 above

j = &i; %Line 2 above

int temp2 = 3; %RHS of line 3 above
j = &temp2; %LHS of line 3 above

(Точнее, есть один ответ на ранее цитированный вопрос, который дает более или менее такое объяснение, но имеет отрицательный балл и не дает комментариев относительно того, что с ним не так.)

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

def foo(b):
   b=2
a=1
foo(a)
print(a)

приводит к 1. В пределах foo локальная переменная-указатель b перенаправляется на адрес нового целочисленного объекта. Внешняя переменная-указатель a по-прежнему указывает на целочисленный объект со значением 1.

Чтобы получить полную картину и понять, как получить доступ к свойству и почему его можно использовать для изменения переменной, которая передается функции в конце концов, я бы добавил утверждение:

Доступ к свойству с . в Python переводится как -> в C ++

Поскольку индексирование является просто синтаксическим сахаром, оно также охватывается этим правилом.

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

РЕДАКТИРОВАТЬ: Еще один очень популярный вопрос , ответы которого противоречат аналогии с указателем

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Правильное объяснение на самом деле таково: У Python есть имена, в других языках есть переменные . Это означает, что переменные Python восстанавливаются путем поиска их имени в dict во время выполнения.

Хотя, я скажу вам, что в первые дни Python я тоже находил это объяснение неутешительным. То, что мне бы понравилось в то время, было бы примером того, что это означает для разработчика.

Переменные в dict

В языках более низкого уровня имя переменной выбрасывается и заменяется компилятором на адрес в памяти. Это не относится к Python, который позволяет вам получить доступ ко всем переменным с помощью встроенной функции vars, которая возвращает переменную области видимости.

Это означает, что вы можете читать переменные из этого слова.

foo = 1
vars()['foo'] # 1

И что вы можете обновить и даже объявить переменную, используя этот dict.

vars()['bar'] = 1
bar # 1

Это также означает, что вы можете перечислить все переменные в области видимости.

foo = 1
bar = 1
vars().keys() # ['__name__', '__doc__', ... , 'foo', 'bar'])

Исключение NameError

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

try:
    print(foo)
except NameError:
    print('foo does not exist') # This is printed

Нет указателей

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

В частности, это означает, что вы можете удалить имя и запретить любой доступ к его значению.

foo = object()
del foo
# The above object is now completely out of reach

То, что сделано выше, это удаление ключа 'foo' в диктовке vars().

0 голосов
/ 09 мая 2018

Это немного (ну, намного) сложнее, чем тогда. Однако, проще говоря, да, каждый объект python является указателем на PyObject или PyVarObject, как определено в object.c

/* Nothing is actually declared to be a PyObject, but every pointer to
 * a Python object can be cast to a PyObject*.  This is inheritance built
 * by hand.  Similarly every pointer to a variable-size Python object can,
 * in addition, be cast to PyVarObject*.
 */
typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...