Веб-версияОткрыть в Telegram

СообщениеList astonishment

9 мая 2023
P
List astonishment Допустим, мы хотим написать функцию, которая будет принимать на вход список. Естественным ходом выглядит написать что-то вроде: >>> def foo(data=[]): ... data.append(5) ... return data Ждем, что при каждом новом вызовы функции список снова будет пустым. На самом же деле: >>> foo() [5] >>> foo() [5, 5] >>> foo() [5, 5, 5] Вот это поворот! Причина такого поведения в том, что в Python значения дефолтных аргументов вычисляются только один раз -- при объявлении функции. То есть, после того, как инструкция def выполнена, список data уже создан. При этом пока функция существует, пересоздаваться список больше не будет. Это объясняет и вот такое поведение: >>> foo(data=[1, 2, 3]) [1, 2, 3, 5] >>> foo() [5, 5, 5] Видно, что, когда мы передали другой список в foo(), к нему добавилось значение 5. При этом аргумент по умолчанию не изменился. Как с этим жить? Либо вообще не использовать изменяемые объекты в качестве дефолтных значний, либо инициализировать их как None: >>> def bar(data=None): ... if data is None: ... data = [] ... data.append(5) ... return data Такое определение создает новый список в локальном неймспейсе. Теперь все чисто😏 >>> bar() [5] >>> bar() [5] >>> bar(data=[1, 2, 3]) [1, 2, 3, 5] На самом деле это поведение можно обратить в свою пользу. Пусть, например, в программе есть функция, которая долго вычисляет результат. Можно кешировать параметры и результат вычисления, и, если функцию вызывают еще раз с теми же парметрами, просто возвращать заранее посчитанный ответ. def baz(arg1, arg2, _cache={}): # Если есть в кеше, выходим if (arg1, arg2) in _cache: return _cache[(arg1, arg2)] # Вычисляем результат result = ... # Сохраняем в кеш _cache[(arg1, arg2)] = result return result Сохранение результатов для предотвращения повторных вычислений называется мемоизацией. В Python дефолтные аргументы инициализируются только при объявлении функции. Это значит, что изменения, которые делаются в мутабельных аргументах при вызове функции, сохраняются. Поэтому лучше не использовать списки, словари и экземпляры самописных классов как значения по умолчанию. Либо использовать специально, как кеш, в котором можно хранить полезную информацию🐍 Закончу цитатой: Не повторяйте одну и ту же ошибку несколько раз. Напишите функцию с этой ошибкой и вызывайте, когда будет нужно.
2 · 310 ·

Рядом в ленте

PPYTHON IN DEPTH🐍Странная переменная в Python. Когда человек впервые видит в программе что-то вроде _, v in my_dict.items(): pass он обычно теряется. Что это за переменная “_”? PPYTHON IN DEPTH🐍Одинарное подчеркивание в конце переменной Недавно говорила об одинарном символе подчеркивания в Python. Теперь поговорим о подчеркивании в конце переменной: my
это сообщение
PPYTHON IN DEPTH🐍for ... else? Рассмотрим пример использования ключевого слова else в цикле while: >>> i = 1 >>> while i < 4: ... print(i) ... i += 1 ... else: ... print('Вышли PPYTHON IN DEPTH🐍Timsort Для сортировки в CPython используется алгоритм Timsort, который его создатель Тим Петерс застенчиво назвал в честь себя😏. Timsort — это комбинация сорти
🐍🐍Python🪆🐍Python🪆@python_chat_ru · группа · Технологии
20участников39сообщений в индексе
Лента площадки Открыть в Telegram

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем