🎯 Цель: Найти, почему переменная ведёт себя не так, как ожидается
📍 Ситуация:
У тебя есть простой код, который должен собирать данные в список из файла:
results = []
def process_file(path):
for line in open(path):
if "error" in line:
results.append(line.strip())
# где-то в другом месте:
process_file("logs1.txt")
process_file("logs2.txt")
print(f"Total errors: {len(results)}")
Но после запуска ты получаешь:
Total errors: 0
🙃 Хотя ты уверен, что в обоих файлах есть строки с
"error".🧩 Задача:
1. Почему список
results остаётся пустым? 2. Почему нет ошибки при обращении к
results.append(...)? 3. Что будет, если вместо
append() просто написать results = [...] внутри функции? 4. Как правильно модифицировать глобальную переменную?
5. Как сделать поведение явным и безопасным?
🛠 Решение:
🔸 Проблема в области видимости переменных:
Функция использует
results, определённый вне функции, но не объявляет его как global. Однако
results.append(...) — это допустимая операция, так как она не переназначает переменную, а вызывает метод объекта.Если бы внутри функции была строка
results = [...], Python бы создал локальную переменную results, и тогда append бы вызывал UnboundLocalError.🔸 Для ясности и чистоты кода лучше делать так:
def process_file(path, results):
for line in open(path):
if "error" in line:
results.append(line.strip())
results = []
process_file("logs1.txt", results)
process_file("logs2.txt", results)
Или, если обязательно нужно использовать глобальную переменную:
results = []
def process_file(path):
global results
for line in open(path):
if "error" in line:
results.append(line.strip())
🔸 Проверка:
-
print(locals()) — покажет локальные переменные-
print(globals()) — покажет глобальные📌 Вывод:
В Python изменение содержимого изменяемой глобальной переменной внутри функции возможно без
global, но присваивание новой переменной требует явного global. Это тонкое поведение, которое часто приводит к ошибкам, особенно при работе со списками и словарями.