Переменные Python: имена и их связи с данными в памяти
Значение переменной в Python как связь с объектом
В Python имя переменной не вмещает ни само число, ни строку, ни список. Оно хранит ссылку на объект, находящийся в памяти. Запись x = 5 означает, что имя x начинает указывать на объект со значением 5. Значением переменной называют объект, к которому можно обратиться через это имя.
Каким способом создать переменную с нужным значением?
city = 'Москва'
population = 13000000
print(city)
print(population)значение переменной в коде python (значение переменной в коде python)
Москва 13000000
изменить значение переменной python (изменение значения переменной в python)
Прямое присваивание подходит для ввода нового имени и для замены существующей ссылки на другую. После повторного присваивания старое значение может исчезнуть, если на него не осталось других ссылок.
token = 'abc'
token = 12345
print(token)
12345
Значение переменной не закреплено за одним типом.
Какая ошибка появляется при чтении значения несуществующей переменной?
print(not_defined)
NameError: name 'not_defined' is not defined
Поиск значения выполняется только после того, как имя было связано с объектом. Ошибка возникает, если такого присваивания не происходило.
Присваивание одной переменной другой переменной
Как влияет значение одной переменной на другую при присваивании?
first = 100
second = first
first = 200
print(second)
100
Для числа переменная second сохранила ссылку на прежний объект. Переменная first перешла на другой объект, и прошлое значение не изменилось.
left = [1, 2]
right = left
left.append(3)
print(right)
[1, 2, 3]
Список относится к изменяемым объектам. Операция append изменила сам объект, поэтому обе ссылки показывают обновленный список. Такой вариант применяется, когда необходимо передать объект без создания копии.
Почему изменение значения через одну переменную заметно через другую?
Переменная right не получила копию списка. Она получила ту же ссылку. Для отдельного объекта используется метод copy или модуль copy.
Множественное присваивание и распаковка
Как распределить несколько значений между переменными одной строкой?
hour, minute, second = 10, 30, 15
print(hour, minute, second)
10 30 15
Правая часть выражения превращается в кортеж, а левая часть распаковывает его по позициям. Количество имен слева должно совпадать с числом элементов справа.
a = 1
b = 2
a, b = b, a
print(a, b)
2 1
Такая запись заменяет временную переменную при обмене значений.
Что происходит при несовпадении количества элементов и переменных?
try:
key_one, key_two = 1, 2, 3
except ValueError as error:
print(error)
too many values to unpack (expected 2)
Интерпретатор сообщает о невозможности распаковать данные.
Присваивание с вычислением нового значения
Как использовать текущее значение переменной для получения другого значения?
total = 5
total = total + 3
print(total)
8
Правая часть сначала читает текущее значение total, затем выполняет сложение и связывает имя total с новым объектом.
Как сократить запись изменения переменной?
total = 10
total -= 2
total *= 3
print(total)
24
Операторы -= и *= выполняют действие и присваивание результата. Для списков операция += ведет себя иначе.
list_value = [1]
list_value += [2]
print(list_value)
text_value = 'a'
text_value += 'b'
print(text_value)
[1, 2] ab
Список изменяется на месте, строка создает новый объект. Это отличие важно при передаче значений между частями программы.
Какая путаница возникает вокруг оператора +=?
Для неизменяемых объектов создается новый объект, для изменяемых списков вызывается изменение текущего объекта. Оба случая выглядят одинаково, но последствия для общих ссылок разные.
Сравнение значений переменных
Как понять, что две переменные содержат одинаковые значения или ссылаются на один объект?
first_list = [1, 2]
second_list = [1, 2]
third_list = first_list
print(first_list == second_list)
print(first_list is second_list)
print(first_list is third_list)
True False True
Оператор == сравнивает содержимое объектов. Оператор is проверяет идентичность ссылок.
Какое значение переменной подходит для сравнения через is?
empty_value = None
print(empty_value is None)
True
None существует в программе как одиночный объект. Для него сравнение with is является общепринятой проверкой отсутствия значения.
В чем опасность замены == на is?
is сравнивает ссылки, а не значение. Два разных объекта могут иметь одинаковое содержимое, но не совпадать по ссылке.
Имя переменной в словаре глобального пространства имен
Когда имя создано на верхнем уровне модуля, Python помещает его в словарь глобального пространства имен. Значение доступно через обычное имя и через строковый ключ словаря.
status = 'active'
print(globals()['status'])
active
Обращение к переменной через словарь показывает связь между именем и значением. В обычном коде такая форма применяется редко.
Локальные имена внутри функции
Локальные переменные размещаются во временном пространстве имен функции. Функция locals() возвращает словарь с текущими значениями.
def example():
local_sum = 12
print(locals()['local_sum'])
example()
12
Словарь локальных переменных существует только во время выполнения функции.
Передача значения переменной в функцию
Параметр функции получает значение той переменной, которая указана в вызове. Для списков это означает передачу ссылки на исходный объект.
def add_item(collection, item):
collection.append(item)
fruits = ['apple']
add_item(fruits, 'banana')
print(fruits)
['apple', 'banana']
Внутри функции не создавался новый список. Изменение объекта, полученного по ссылке, видно через исходное имя fruits.
Копирование вложенных изменяемых значений
Метод copy для списка не копирует вложенные объекты. Операция умножения списка способна создать несколько ссылок на один внутренний список.
rows = [[0]] * 3
rows[0][0] = 7
print(rows)
[[7], [7], [7]]
Все три элемента rows указывают на один и тот же список. Изменение одного элемента заметно во всех трех позициях.
rows = [[0] for _ in range(3)]
rows[0][0] = 7
print(rows)
[[7], [0], [0]]
Генератор списка создает три разных внутренних списка. Поэтому изменение затрагивает только первую строку.
Глубокая копия значения
Модуль copy предоставляет функцию deepcopy, которая отделяет все уровни вложенности.
from copy import deepcopy
original = [[1, 2], [3, 4]]
copy_deep = deepcopy(original)
copy_deep[0].append(9)
print(original)
print(copy_deep)
[[1, 2], [3, 4]] [[1, 2, 9], [3, 4]]
Глубокое копирование создает отдельные объекты для каждого вложенного списка.
Удаление имени и доступ к значению
Команда del убирает имя из текущего пространства имен. Объект остается доступным, если существует другая ссылка.
item = 'abc'
other = item
del item
print(other)
abc
Переменная other продолжает указывать на ту же строку. При отсутствии других ссылок объект становится доступен сборщику мусора.
Именованное выражение walrus
Оператор := присваивает значение переменной и сразу возвращает его. Такая запись уменьшает дублирование условия.
words = ['', 'один', 'два']
while (word := words.pop()):
print(word)
два один
Метод pop списка извлекает элемент с конца. При одном из вызовов pop возвращает пустую строку, которая считается ложным значением, и цикл завершается.