Я только начал Python, и я понятия не имею, что такое памятка и как ее использовать. Кроме того, могу ли я иметь упрощенный пример?
python
memoization
blur959
источник
источник
Ответы:
Под «запоминанием» фактически понимается запоминание («памятка» → «меморандум» → запоминание) результатов вызовов метода на основе входных данных метода и затем возвращение запомненного результата, а не его повторный расчет. Вы можете думать об этом как о кеше для результатов метода. Для получения дополнительной информации см. Стр. 387 для определения в разделе Введение в алгоритмы (3e), Cormen et al.
Простой пример вычисления факториалов с использованием мемоизации в Python будет выглядеть примерно так:
Вы можете усложнить задачу и включить процесс запоминания в класс:
Затем:
В Python 2.4 была добавлена функция, известная как « декораторы », которая позволяет вам просто написать следующее, чтобы выполнить то же самое:
В библиотеке Python Decorator есть похожий декоратор,
memoized
который называется несколько более надежным, чемMemoize
класс, показанный здесь.источник
factorial_memo
, потому чтоfactorial
внутренняя частьdef factorial
все еще вызывает старую команду unmemoizefactorial
.if k not in factorial_memo:
, что читает лучше, чемif not k in factorial_memo:
.args
это кортеж.def some_function(*args)
делает аргументы кортежемНовое в Python 3.2 есть
functools.lru_cache
. По умолчанию, он кэширует только 128 недавно использованные звонков, но вы можете установить ,maxsize
чтобыNone
указать , что кэш никогда не должен истекать:Эта функция сама по себе очень медленная, попробуйте,
fib(36)
и вам придется подождать около десяти секунд.Добавление
lru_cache
аннотации гарантирует, что если функция была вызвана недавно для определенного значения, она не будет повторно вычислять это значение, а будет использовать кэшированный предыдущий результат. В этом случае это приводит к огромному улучшению скорости, в то время как код не загроможден деталями кэширования.источник
fib
вызове он должен вернуться к базовому сценарию, прежде чем произойдет запоминание. Итак, ваше поведение примерно ожидаемо.Другие ответы охватывают то, что это довольно хорошо. Я не повторяю это. Просто некоторые моменты, которые могут быть полезны для вас.
Обычно запоминание - это операция, которую вы можете применить к любой функции, которая вычисляет что-то (дорогое) и возвращает значение. Из-за этого это часто реализуется как декоратор . Реализация проста, и это было бы что-то вроде этого
или выраженный как декоратор
источник
Мемоизация хранит результаты дорогостоящих вычислений и возвращает кэшированный результат, а не непрерывно пересчитывает его.
Вот пример:
Более полное описание можно найти в записи в Википедии о запоминании .
источник
if input not in self.cache
иself.cache[input]
(has_key
устарело, поскольку ... в начале серии 2.x, если не 2.0,self.cache(index)
никогда не было верным. IIRC)Давайте не будем забывать встроенную
hasattr
функцию, для тех, кто хочет ручной работы. Таким образом, вы можете хранить кеш mem внутри определения функции (в отличие от глобального).источник
Я нашел это чрезвычайно полезным
источник
functools.wraps
.memo
чтобы освободить память?Memoization - это, в основном, сохранение результатов прошлых операций, выполненных с помощью рекурсивных алгоритмов, чтобы уменьшить необходимость обхода дерева рекурсии, если такой же расчет требуется на более поздней стадии.
см. http://scriptbucket.wordpress.com/2012/12/11/introduction-to-memoization/
Пример запоминания Фибоначчи в Python:
источник
Мемоизация - это преобразование функций в структуры данных. Обычно требуется, чтобы преобразование происходило постепенно и лениво (по требованию данного элемента домена - или «ключа»). В ленивых функциональных языках это ленивое преобразование может происходить автоматически, и, таким образом, запоминание может быть реализовано без (явных) побочных эффектов.
источник
Ну, я должен ответить на первую часть в первую очередь: что такое запоминание?
Это просто способ обменять память на время. Подумайте о таблице умножения .
Использование изменяемого объекта в качестве значения по умолчанию в Python обычно считается плохим. Но если использовать его с умом, это может быть полезно для реализации
memoization
.Вот пример, адаптированный из http://docs.python.org/2/faq/design.html#why-are-default-values-shared-between-objects
Используя изменяемый
dict
в определении функции, промежуточные вычисленные результаты могут быть кэшированы (например, при вычисленииfactorial(10)
после вычисленияfactorial(9)
мы можем повторно использовать все промежуточные результаты)источник
Вот решение, которое будет работать с аргументами типа list или dict без нытья:
Обратите внимание, что этот подход можно естественным образом распространить на любой объект, реализовав собственную хеш-функцию в качестве особого случая в handle_item. Например, чтобы этот подход работал для функции, которая принимает набор в качестве входного аргумента, вы можете добавить к handle_item:
источник
list
аргумент[1, 2, 3]
может ошибочно считаться другимset
аргументом со значением{1, 2, 3}
. Кроме того, наборы неупорядочены, как словари, поэтому они также должны бытьsorted()
. Также обратите внимание, что рекурсивный аргумент структуры данных может вызвать бесконечный цикл.list
s иset
s «дублируются» в одно и то же и поэтому становятся неотличимыми друг от друга.sets
Я не боюсь, что пример кода для добавления поддержки, описанный в вашем последнем обновлении. Это легко увидеть, отдельно передав[1,2,3]
и{1,2,3}
в качестве аргумента d-функции «memoize» и посмотрев, вызывается ли она дважды, как и должно быть, или нет.list
с иdict
потому , что это возможно дляlist
иметь точно такую же вещь в нем , что в результате вызоваmake_tuple(sorted(x.items()))
для словаря. Простым решением для обоих случаев было бы включениеtype()
значения в сгенерированный кортеж. Я могу придумать еще более простой способ обработкиset
s, но он не обобщает.Решение, которое работает как с позиционными аргументами, так и с ключевыми словами независимо от порядка, в котором были переданы аргументы ключевого слова (с использованием inspect.getargspec ):
Аналогичный вопрос: определение эквивалентных вызовов функции varargs для запоминания в Python
источник
источник
if n not in cache
вместо этого. использованиеcache.keys
создаст ненужный список в python 2Хотелось бы добавить к уже предоставленным ответам, библиотека декоратора Python имеет несколько простых, но полезных реализаций, которые, в отличие от этого, могут также запоминать «не подлежащие обработке типы»
functools.lru_cache
.источник