← Назад ко всем вопросам

Почему использовать изменяемые объекты как параметры по-умолчанию плохо?

1️⃣ Как кратко ответить

Использование изменяемых объектов как параметров по умолчанию в функциях может привести к неожиданным результатам, так как они сохраняют свое состояние между вызовами функции. Это может вызвать непредсказуемое поведение программы, если объект будет изменен.

2️⃣ Подробное объяснение темы

В Python параметры по умолчанию функции вычисляются один раз в момент определения функции, а не каждый раз при ее вызове. Это означает, что если параметр по умолчанию является изменяемым объектом, например, списком или словарем, то изменения, внесенные в этот объект, сохранятся между вызовами функции. Это может привести к неожиданным и нежелательным результатам.

Пример

Рассмотрим функцию, которая добавляет элемент в список:

def append_to_list(value, my_list=[]):
    my_list.append(value)
    return my_list

Что происходит в этом коде:

  • my_list=[]: Здесь my_list — это параметр по умолчанию, который является изменяемым объектом (списком).
  • my_list.append(value): Эта строка добавляет value в список my_list.
  • return my_list: Возвращает измененный список.

Проблема

Если вызвать эту функцию несколько раз, не передавая второй аргумент, то изменения в списке будут сохраняться между вызовами:

print(append_to_list(1))  # Вывод: [1]
print(append_to_list(2))  # Вывод: [1, 2]
print(append_to_list(3))  # Вывод: [1, 2, 3]

Каждый вызов функции добавляет элемент в один и тот же список, который был создан при первом вызове функции.

Решение

Чтобы избежать этой проблемы, следует использовать None в качестве значения по умолчанию и создавать новый объект внутри функции:

def append_to_list(value, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(value)
    return my_list

Что происходит в этом коде:

  • my_list=None: Устанавливаем None в качестве значения по умолчанию.
  • if my_list is None: my_list = []: Если my_list равен None, создаем новый список.
  • my_list.append(value): Добавляем value в новый или переданный список.
  • return my_list: Возвращаем измененный список.

Пример использования исправленной функции

print(append_to_list(1))  # Вывод: [1]
print(append_to_list(2))  # Вывод: [2]
print(append_to_list(3))  # Вывод: [3]

Теперь каждый вызов функции создает новый список, и изменения не сохраняются между вызовами.

Тема: Python
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки