В коде на Python: def append_to_list(x, lst=[]): lst.append(x); return lst. Объясните проблему с использованием изменяемых аргументов по умолчанию и предложите несколько безопасных альтернатив в разных контекстах

9 Дек 2025 в 05:36
81 +1
0
Ответы
1
Проблема: значение аргумента по умолчанию вычисляется один раз при определении функции, поэтому если это изменяемый объект (например список), все вызовы без явно переданного аргумента будут использовать и мутировать один и тот же объект.
Пример (небезопасно):
```
def append_to_list(x, lst=[]):
lst.append(x)
return lst
```
Поведение:
- первый вызов append_to_list(1) вернёт [1][1][1],
- второй вызов append_to_list(2) вернёт [1,2][1, 2][1,2],
- третий вызов append_to_list(3) вернёт [1,2,3][1, 2, 3][1,2,3].
Безопасные альтернативы
1) Стандартный паттерн с None (рекомендуется):
```
def append_to_list(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
```
Используйте, когда нужно новый список по умолчанию при каждом вызове.
2) Возврат нового списка (функция не мутирует вход):
```
def append_to_list(x, lst=None):
if lst is None:
return [x]
return lst + [x] # создает новый список
```
Полезно в функциональном стиле или когда нельзя изменять переданный объект.
3) Копирование входного списка (если нужно сохранить переданный объект неизменным):
```
def append_to_list(x, lst=None):
lst_copy = list(lst) if lst is not None else []
lst_copy.append(x)
return lst_copy
```
4) Если нужен именно накопитель между вызовами (явное сохранение состояния):
- явный глобальный/замыкание/атрибут функции:
```
def make_appender():
lst = []
def append(x):
lst.append(x)
return lst
return append
app = make_appender()
```
или
```
def append_to_list(x, _state=[]): # сознательно использовать один список, но документировать это
_state.append(x)
return _state
```
(использовать только если такое поведение желаемо и понятно).
5) Для классов и dataclass:
- В __init__ присваивайте новый список: `self.lst = []`, не используйте `def __init__(..., lst=[])`.
- В dataclass:
```
from dataclasses import dataclass, field
@dataclass
class C:
lst: list = field(default_factory=list)
```
Краткое правило: не используйте изменяемые объекты как значения по умолчанию, если вы не хотите, чтобы состояние сохранялось между вызовами; вместо этого используйте None + создание нового объекта или default_factory (dataclass).
9 Дек 2025 в 06:28
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир