variable script passing passed pass parameter number python performance argument-passing static-variables memoization

script - python pass by reference



Memoria eficiente en Python (2)

Los diferentes estilos de acceso variable ya han sido cronometrados y comparados en: http://code.activestate.com/recipes/577834-compare-speeds-of-different-kinds-of-access-to-var Aquí hay un breve resumen: el acceso local supera el no local (ámbitos anidados) que supera el acceso global (alcance del módulo), que supera el acceso a los elementos integrados.

Tu solución # 2 (con acceso local) debería ganar. La solución # 3 tiene una búsqueda de puntos lentos (que requiere una búsqueda de diccionario). La solución # 1 usa acceso no local (alcance anidado) que usa variables de celda (más rápido que una búsqueda de dictados pero más lento que los locales).

También tenga en cuenta que la clase de excepción KeyError es una búsqueda global y puede acelerarse localizándola. Podría reemplazar el try / except por completo y usar un memo.get(n, sentinel) lugar. E incluso eso podría acelerarse utilizando un método enlazado. Por supuesto, su aumento de velocidad más fácil puede venir de probar pypy :-)

En resumen, hay muchas formas de modificar este código. Solo asegúrate de que valga la pena.

Tengo algunas tareas que resolver y la parte más importante en este momento es hacer que el script sea lo más eficiente posible. Uno de los elementos que estoy tratando de optimizar es la memoria dentro de una de las funciones.

Así que mi pregunta es: ¿Cuál de los siguientes métodos 3-4 es el método más eficiente / rápido para implementar la memorización en Python?

He proporcionado el código solo a modo de ejemplo: si uno de los métodos es más eficiente, pero no en el caso que mencioné, comparta lo que sabe.

Solución 1 - usando una variable mutable desde el alcance externo

Esta solución se muestra a menudo como ejemplo de memoria, pero no estoy seguro de qué tan eficiente es. He escuchado que el uso de variables globales (en este caso es variable desde un ámbito externo, no global) es menos eficiente.

def main(): memo = {} def power_div(n): try: return memo[n] except (KeyError): memo[n] = (n ** 2) % 4 # example expression, should not matter return memo[n] # extensive usage of power_div() here

Solución 2 - usando el argumento por defecto, mutable

He encontrado en algún lugar que el uso de argumentos mutables predeterminados se ha utilizado en el pasado para pasar variables desde el ámbito externo, cuando Python buscó primero la variable en el ámbito local, luego en el ámbito global, omitiendo el ámbito no local (en este caso, el ámbito dentro de función main() ). Debido a que el argumento predeterminado se inicializa solo en el momento en que se define la función y es accesible solo dentro de la función interna, tal vez sea más eficiente.

def main(): def power_div(n, memo={}): try: return memo[n] except (KeyError): memo[n] = (n ** 2) % 4 # example expression, should not matter return memo[n] # extensive usage of power_div() here

¿O quizás la siguiente versión (al ser de hecho una combinación de soluciones 1 y 2) es más eficiente?

def main(): memo = {} def power_div(n, memo=memo): try: return memo[n] except (KeyError): memo[n] = (n ** 2) % 4 # example expression, should not matter return memo[n] # extensive usage of power_div() here

Solución 3 - atributo de la función

Este es otro ejemplo bastante común de memoización en Python: el objeto de memoización se almacena como un atributo de la función en sí.

def main(): def power_div(n): memo = power_div.memo try: return memo[n] except (KeyError): memo[n] = (n ** 2) % 4 # example expression, should not matter return memo[n] # extensive usage of power_div() here

Resumen

Estoy muy interesado en sus opiniones acerca de las cuatro soluciones anteriores para la memoria. También es importante que la función que utiliza la memorización esté dentro de otra función.

Sé que también hay otras soluciones para la memoización (como el decorador Memoize ), pero me cuesta creer que esta sea una solución más eficiente que las enumeradas anteriormente. Corrígeme si estoy equivocado.

Gracias por adelantado.


Para el beneficio de las personas que se topan con esta pregunta mientras buscan una manera de hacer la memorización en python, recomiendo fastcache .

Funciona en Python 2 y 3, es más rápido que cualquiera de los métodos descritos anteriormente y ofrece la opción de limitar el tamaño de la memoria caché para que no se vuelva demasiado grande inadvertidamente:

from fastcache import clru_cache @clru_cache(maxsize=128, typed=False) def foo(cat_1, cat_2, cat_3): return cat_1 + cat_2 + cat_3

Instalar fastcache es simple, usando pip :

pip install fastcache

o conda

conda install fastcache