¿Simplificar / refactorizar automáticamente el código de Python (por ejemplo, para bucles -> comprensión de lista)?

En Python, realmente disfruto lo concisa que puede ser una implementación al usar la comprensión de listas. Me encanta hacer listas concisas de comprensión esto:

myList = [1, 5, 11, 20, 30, 35] #input data bigNumbers = [x for x in myList if x > 10] 

Sin embargo, a menudo encuentro implementaciones más detalladas como esta:

 myList = [1, 5, 11, 20, 30, 35] #input data bigNumbers = [] for i in xrange(0, len(myList)): if myList[i] > 10: bigNumbers.append(myList[i]) 

Cuando un for loop solo mira a través de una estructura de datos (por ejemplo, myList[] ), generalmente hay una statement de comprensión de lista directa que es equivalente al bucle.
Teniendo esto en cuenta, ¿existe una herramienta de refactorización que convierta bucles de Python detallados en declaraciones de comprensión de lista concisa?


Las preguntas anteriores de StackOverflow han pedido consejo sobre cómo transformar los bucles en una lista de comprensión. Pero, todavía tengo que encontrar una pregunta sobre la conversión automática de bucles en expresiones de comprensión de lista.


Motivación: hay muchas formas de responder a la pregunta “¿qué significa que el código esté limpio?” Personalmente, encuentro que hacer que el código sea conciso y deshacerse de parte de la pelusa tiende a hacer que el código sea más limpio y más legible. Naturalmente, hay una línea en la arena entre “código conciso” e “incomprensibles de una sola línea”. Sin embargo, a menudo me resulta satisfactorio escribir y trabajar con código conciso.

2to3 es una herramienta de refactorización que puede realizar refactorizaciones arbitrarias, siempre que pueda especificarlas con un patrón sintáctico. El patrón que podrías querer buscar es este

 VARIABLE1 = [] for VARIABLE2 in EXPRESSION1: if EXPRESSION2: VARIABLE1.append(EXPRESSION3) 

Esto puede ser refaccionado con seguridad para

 VARIABLE1 = [EXPRESSION3 for VARIABLE2 in EXPRESSION1 if EXPRESSION2] 

En su ejemplo específico, esto daría

 bigNumbers = [myList[i] for i in xrange(0, len(myList)) if myList[i] > 10] 

Luego, puede tener otra refactorización que reemplace xrange (0, N) con xrange (N), y otra que reemplace

 [VARIABLE1[VARIABLE2] for VARIABLE2 in xrange(len(VARIABLE1)) if EXPRESSION1] 

con

 [VARIABLE3 for VARIABLE3 in VARIABLE1 if EXPRESSION1PRIME] 

Hay varios problemas con esta refactorización:

  • EXPRESSION1PRIME debe ser EXPRESSION1 con todas las apariciones de VARIABLE1[VARIABLE2] reemplazadas por VARIABLE3. Esto es posible con 2to3, pero requiere un código explícito para hacer el recorrido y el reemplazo.
  • EXPRESSION1PRIME no debe contener más apariciones de VARIABLE1 . Esto también se puede comprobar con código explícito.
  • Uno tiene que llegar a un nombre para VARIABLE3. Has elegido x ; No hay una manera razonable de hacer esto automáticamente. Podría elegir reciclar VARIABLE1 (es decir, i ) para eso, pero eso puede ser confuso ya que sugiere que i todavía es un índice. Podría funcionar elegir un nombre sintético, como VARIABLE1_VARIABLE2 (es decir, myList_i ), y verificar si no se usa de otra manera.
  • Uno debe estar seguro de que VARIABLE1 [VARIABLE2] produce el mismo resultado que obtiene al usar iter(VARIABLE1) . No es posible hacer esto automáticamente.

Si quieres aprender a escribir fijadores 2to3, echa un vistazo al libro de Lennart Regebro .