2025, Dec 14 21:01

Return без присваивания: почему позиция не меняется и как это исправить в Python

Разбираем типичную ошибку в Python: return без присваивания. На примере текстового квеста показываем, почему локация не меняется и как исправить код строкой.

Когда вы создаёте простые текстовые приключения или парсеры команд, распространённая ловушка — ожидать, что один лишь вызов функции сам по себе обновит переменную. Если функция возвращает значение, но вы его не сохраняете, за пределами функции ничего не меняется. Никакой магии и никаких скрытых побочных эффектов — просто возвращаемое значение без присваивания.

Ситуация: перемещение между локациями

Ниже — минимальный пример, который пытается переместить игрока между связанными областями. Логика корректная: разобрать команду вроде “go north”, сверить её с картой, вычислить новую позицию и вернуть её. Однако отображаемая локация так и не меняется.

zones = {
    'geysers': {'north': 'caves', 'south': 'fields', 'east': 'swamps', 'west': 'treetops', 'item': 'start'},
    'caves': {'south': 'geysers', 'east': 'cliffs', 'item': 'sword'},
    'fields': {'north': 'geysers', 'east': 'temple', 'item': 'bandages'},
    'swamps': {'north': 'pond', 'west': 'geysers', 'item': 'tranquilizer'},
    'treetops': {'east': 'geysers', 'item': 'blowtorch'},
    'cliffs': {'west': 'caves', 'item': 'shield'},
    'pond': {'south': 'swamps', 'item': 'javelin'},
    'temple': {'west': 'fields', 'item': 'villain'}
}

active_spot = 'geysers'


def bad_shift():
    print('Move not valid. Try again.')


user_cmd = input('Enter your move:\n>').lower().split()


def step_actor(place, cmd):
    fresh_place = place
    if cmd[0] == 'go':
        if cmd[1] in zones[place] and cmd[1] != 'item':
            fresh_place = zones[place][cmd[1]]
        else:
            bad_shift()
    else:
        bad_shift()
    return fresh_place


step_actor(active_spot, user_cmd)
print(active_spot)

Что на самом деле происходит

Функция вычисляет новую локацию и возвращает её через return. Но результат вызова игнорируется. В итоге внешняя переменная, в которой хранится текущая позиция, остаётся без изменений, и print(active_spot) выводит исходное значение.

Вы вызываете move_player(), но нигде не сохраняете возвращаемое значение. Видимо, вы хотели написать current_location = move_player(...)

Решение

Присвойте возвращаемое значение обратно переменной, которая отслеживает текущую локацию. На этом вся проблема и заканчивается.

active_spot = step_actor(active_spot, user_cmd)
print(active_spot)

Если по какой‑то причине нужно сохранить предыдущее положение, запишите его отдельно перед перезаписью.

Почему это важно

Когда функция возвращает значение, снаружи ничего не изменится, пока вы явно не сохраните этот результат. Забытое присваивание приводит к запутывающим «пустым» вызовам, которые на первый взгляд выглядят верно — особенно в игровых циклах и обработчиках команд.

Главная мысль

Если функция возвращает обновлённое состояние, привяжите его к переменной. Либо обновляйте исходную переменную, либо храните и старое, и новое значение — в зависимости от задачи. В нашем случае установите active_spot = step_actor(active_spot, user_cmd), чтобы на экране отображалось перемещение, которое вы только что вычислили.