Что выведет этот код?


def test(a, b=[]):
    b.append(a)
    return b

print(test(1))
print(test(2, [3]))

Результат выполнения кода:

[1]
[3, 2]

Объяснение:

Функция test имеет аргумент по умолчанию b=[]. Это означает, что b инициализируется пустым списком только один раз при определении функции. При первом вызове test(1), к этому общему списку добавляется 1, и возвращается [1].

При втором вызове test(2, [3]), аргумент b явно передается как [3]. К этому новому списку добавляется 2, и возвращается [3, 2].


Разбор задачи с аргументами по умолчанию в Python

Эта задача иллюстрирует классическую ловушку, связанную с использованием изменяемых объектов (в данном случае, списка) в качестве значений аргументов по умолчанию в Python.

Функция `test(a, b=[])`

  • Функция принимает два аргумента: `a` (обязательный) и `b` (необязательный).
  • Аргумент `b` имеет значение по умолчанию `[]` (пустой список). Ключевой момент: Этот список создается только один раз при определении функции.
  • Внутри функции `test`, элемент `a` добавляется в список `b` с помощью метода `append()`.
  • Функция возвращает список `b`.

Результат `print(test(1))`

  1. Вызывается функция `test` с `a = 1` и `b` использует значение по умолчанию `[]`.
  2. В список `b` добавляется элемент `1`. Теперь `b` равен `[1]`.
  3. Функция возвращает `[1]`, и это выводится на экран.

Результат `print(test(2, [3]))`

  1. Вызывается функция `test` с `a = 2` и `b = [3]` (аргумент `b` передан явно).
  2. В список `b` добавляется элемент `2`. Теперь `b` равен `[3, 2]`.
  3. Функция возвращает `[3, 2]`, и это выводится на экран.

Опасность аргументов по умолчанию с изменяемыми объектами

Если бы мы сделали еще один вызов `print(test(4))`, то результат был бы `[1, 4]`, а не `[4]`, как можно было бы ожидать. Это происходит потому, что `b` в первом вызове `test(1)` и последующих вызовах без явного указания `b` - это один и тот же объект списка в памяти.

Правильное решение

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


def test_safe(a, b=None):
  if b is None:
    b = []
  b.append(a)
  return b

print(test_safe(1))
print(test_safe(2, [3]))
print(test_safe(4))

В этом случае, каждый вызов `test_safe` без явного указания `b` будет начинать с нового пустого списка.

0