Этот вопрос приводит к некоторым забавным отклонениям относительно природы объектов python и их сборщика мусора:
Вероятно, полезно понимать, что все переменные в python действительно являются указателями, то есть они являются именами в пространстве имен (реализованном в виде хеш-таблицы), которые указывают на адрес в памяти, где фактически находится объект.
Запрос значения неинициализированной переменной - это то же самое, что запрос значения объекта, на который указывает указатель, когда указатель еще не создан ... это, очевидно, глупость, поэтому самая разумная вещь, которую Python может сделать сделать - бросить значимую ошибку NameError.
Еще одна странность языка Python заключается в том, что, возможно, объект существует задолго до того, как вы выполните оператор присваивания. Рассмотрим:
a = 1
Вы волшебным образом создали здесь объект int (1)? Нет - это уже существовало. Поскольку int (1) является неизменяемым синглтоном, на него уже есть несколько сотен указателей:
>>> sys.getrefcount(a)
592
>>>
Весело, а?
РЕДАКТИРОВАТЬ: комментарий от JFS (размещен здесь, чтобы показать код)
>>> a = 1 + 1
>>> sys.getrefcount(a) # integers less than 256 (or so) are cached
145
>>> b = 1000 + 1000
>>> sys.getrefcount(b)
2
>>> sys.getrefcount(2000)
3
>>> sys.getrefcount(1000+1000)
2