В чем разница между разворотом списка с помощью срезов и метода reverse в Python
Что проверяют
Понимаете ли вы разницу между созданием нового объекта и изменением существующего на месте. По сути это проверка модели данных Python: ссылки, изменяемость, что возвращают методы. Следом часто спрашивают про reversed() и про то, что станет с другими ссылками на тот же список.
Как отвечать
- срез
lst[::-1]: создаёт новый список, исходный не трогает. Копия поверхностная, вложенные объекты у обоих списков общие. Нужна дополнительная память на n ссылок; - метод
lst.reverse(): переставляет элементы на месте и возвращаетNone. Дополнительной памяти почти не требует. Все переменные, которые ссылаются на этот список, увидят новый порядок; reversed(lst): третий вариант, о котором стоит сказать самому. Возвращает ленивый итератор, ничего не копирует, удобен вfor. Но он одноразовый, а изменение списка во время обхода даст путаницу;- сложность: все три варианта линейные по времени, разница в памяти и семантике, а не в асимптотике. В CPython и срез, и
reverse()написаны на C, спорить о микросекундах без замера черезtimeitбессмысленно; - применимость: срез работает для любой последовательности, в том числе для строк и кортежей, у которых метода
reverse()нет, потому что они неизменяемые.reversed()принимает объекты с__reversed__или с парой__len__и__getitem__.
Правило выбора: если исходный порядок ещё нужен или список пришёл аргументом из чужого кода, берите срез или reversed(). Если список ваш, большой и старый порядок не нужен, берите reverse().
Где спотыкаются
Пишут result = lst.reverse() и получают None. Та же история с sort() в отличие от sorted(), и интервьюер часто проверяет это следом.
Разворачивают на месте список, переданный в функцию. Вызывающий код внезапно получает перевёрнутые данные, хотя ничего такого не просил.
Считают, что срез делает полную копию. Для списка словарей изменение словаря в «копии» видно и в оригинале, для независимой копии нужен copy.deepcopy.