python

Объяснение задачи на Python с собеседования

  • четверг, 11 июля 2019 г. в 00:17:49
https://habr.com/ru/company/otus/blog/459518/
  • Блог компании OTUS. Онлайн-образование
  • Python
  • Программирование
  • Карьера в IT-индустрии


Салют, хабровчане! В преддверии запуска нового потока по курсу «Web-разработчик на Python» хотим поделиться новым полезным переводом. Поехали!



Снова сходив на несколько собеседований и пройдя тестовые задания, я заметил, что интервьюерам нравятся задания наподобие следующего.

def f(x, l=[]):
    for i in range(x):
        l.append(i * i)
    return l
>>> f(2)
>>> f(3, [0, 1, 2])
>>> f(3)


Вопрос: Что выведет этот код?

Вывод первых двух строк достаточно очевиден, однако результат выполнения третьей строки f(3) не показался мне таким однозначным. Давайте посмотрим, что происходит после инициализации функции f. Чтобы запустить этот код, я воспользуюсь IPython.

>>> f
<function __main__.f(x, l=[])>
>>> f.__defaults__
([],)


Пустой список, который мы видим из результата выполнения f.__defaults__ — это переменная l в коде функции.

>>> f(2)
[0, 1]


Ничего особенного.

>>> f
<function __main__.f(x, l=[0, 1])>
>>> f.__defaults__
([0, 1],)


Однако! Теперь мы видим, что переменная l имеет значение [0, 1] в силу изменчивости объекта списка в Python и передачи аргументов функции в качестве ссылки.

>>> f(3, [0, 1, 2])
[0, 1, 2, 0, 1, 4]
>>> f
<function __main__.f(x, l=[0, 1])>


Тоже ничего особенного. Просто передача объекта list в качестве переменной l.

>>> f(3)
[0, 1, 0, 1, 4]
>>> f
<function __main__.f(x, l=[0, 1, 0, 1, 4])>


А вот теперь самое интересное. Когда вы запускаете f(3), Python не использует пустой список, который определен в коде функции, он использует переменную l со значениями из f.__defaults__ ([0, 1]).

P.S.

Если вам нужна функция, которая использует пустой список после каждого вызова, вам следует использовать что-то вроде этого (установить значение ‘l’ в ‘None’).

def f(x, l=None):
    if l is None:
        l = []
    for i in range(x):
        l.append(i * i)
    return l
>>> f(2)
[0, 1]
>>> f(3, [0, 1, 2])
[0, 1, 2, 0, 1, 4]
>>> f(3)
[0, 1, 4]


Заключение


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

Надеемся данный перевод станет полезным для вас. Традиционно ждем комментарии и до встречи на курсе.