Discussion:
[pyar] Refactoring de una función
Luis Andraschnik
2018-07-09 15:50:56 UTC
Permalink
Hola gente!

Tengo esta función que toma como argumentos una lista de archivos de
espectros y grafica según los valores de los parámetros en un archivo único
(superpuestos) o separados en archivos individuales. A fin de no repetir
código lo hago en una única función y sólo cambia el final. El cambio es
muy sutil, la posición del if define si se cierra el plot y se guarda el
arhchivo. y sólo cambia qué nombre le asigno a/los archivo/s. Me parece que
falta claridad, un error de indentado me cambia el resultado.

Cómo de puede refactorizar para que quede más claro?
Se puede utilizar el patrón de diseño Template? Cómo?

Saludos

import os
import matplotlib.pyplot as plt
INIT_DIR=os.getcwd()


def ftir_plot(used_oil_name_list, formato='png', absorbancia=True,
superpuestos=True, dpi=300):
'''Grafica espectros infrarrojos
formato : 'png','jpg', 'pdf', etc
absorbancia : True, eje Y absorbancia, False, eje Y transmitancia,
superpuestos: True, se grafica todo en un mismo archivo,
False, cada espectro en un archivo separado,
dpi: resolución en pixels por pulgada.
'''
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
for used_oil in used_oil_name_list:
espectro = cargar_espectro(used_oil)
x_range = espectro.index # Wavenumbers
if absorbancia:
y_range = espectro['abs'] # Absorbancia/Transmitancia
else:
y_range = absorbancia_to_transmitancia(espectro['abs'])

# grafico el espectro
estilo(absorbancia)
label = name_for_legend(used_oil)
plt.plot(x_range, y_range, '-', label = label)
plt.legend(loc=0)
if not superpuestos:
plt.savefig(os.path.join(INIT_DIR, 'ftir_{}.{}'.format(label,
formato)), dpi=dpi)
plt.close()

if superpuestos:
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)),
dpi=dpi)
plt.close()
Mati Barriento
2018-07-09 16:47:24 UTC
Permalink
Me puse el sombrero del refactor y tire esto.
http://linkode.org/#6oT4YaSVl9qqJhmTrejMt2

Basicamente le saque la responsabilidad el metodo de guardar y se lo pase a
una clase que recibe como dependencia. No lo pude probar asi que no sabria
decirte si funciona.
Tal vez no sea la solución más elegante pero te oriente por donde ir (o por
donde no ir).

Saludos
Post by Luis Andraschnik
Hola gente!
Tengo esta función que toma como argumentos una lista de archivos de
espectros y grafica según los valores de los parámetros en un archivo único
(superpuestos) o separados en archivos individuales. A fin de no repetir
código lo hago en una única función y sólo cambia el final. El cambio es
muy sutil, la posición del if define si se cierra el plot y se guarda el
arhchivo. y sólo cambia qué nombre le asigno a/los archivo/s. Me parece que
falta claridad, un error de indentado me cambia el resultado.
Cómo de puede refactorizar para que quede más claro?
Se puede utilizar el patrón de diseño Template? Cómo?
Saludos
import os
import matplotlib.pyplot as plt
INIT_DIR=os.getcwd()
def ftir_plot(used_oil_name_list, formato='png', absorbancia=True,
'''Grafica espectros infrarrojos
formato : 'png','jpg', 'pdf', etc
absorbancia : True, eje Y absorbancia, False, eje Y transmitancia,
superpuestos: True, se grafica todo en un mismo archivo,
False, cada espectro en un archivo separado,
dpi: resolución en pixels por pulgada.
'''
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
espectro = cargar_espectro(used_oil)
x_range = espectro.index # Wavenumbers
y_range = espectro['abs'] # Absorbancia/Transmitancia
y_range = absorbancia_to_transmitancia(espectro['abs'])
# grafico el espectro
estilo(absorbancia)
label = name_for_legend(used_oil)
plt.plot(x_range, y_range, '-', label = label)
plt.legend(loc=0)
plt.savefig(os.path.join(INIT_DIR, 'ftir_{}.{}'.format(label,
formato)), dpi=dpi)
plt.close()
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)),
dpi=dpi)
plt.close()
_______________________________________________
Sitio web: http://www.python.org.ar/
Para administrar la lista (o desuscribirse) entrar a
http://listas.python.org.ar/listinfo/pyar
La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
Argentina - http://www.usla.org.ar
Luis Andraschnik
2018-07-09 17:13:08 UTC
Permalink
Hola Mati

Qué bueno el linkode, hay que registrase?

Al parecer usás composición :

en_uno = EnUnArchivo('png', 400)
ftir_uno = FtirPlot(en_uno) <--- acá pasas una instancia de clase como
argumento que se "enchufa" como método __init__ de FtirPlot

Acá lo pasás a orientación a objetos, y siempre me viene a la cabeza la
charla de Jack Diederich "Stop writting classes". Es la versión OOP más
clara, reusable, mantenible?

Me cuesta ponerme el sombrero de OOP debido a que el código se vuelve tan
"verbose", lo siento no natural.

Gracias , lo voy a probar. Tenía intenciones de pasarlo a OOP para ver que
ventajas tenía además de aprender
Saludos
Luis
Sebastian Bassi
2018-07-09 17:18:41 UTC
Permalink
No sé que es mejor, pero si queres evitar esos 2 if que tenes ahi, podes
poner un

yield (plt, label)

antes del if not superpuestos (y borrar ese if porque la parte de graficar
queda afuera):

asi haces un generador en lugar de una funcion y el hecho de grabar 1 o
multiples juntos lo decidis por afuera, al momento de llamarla, tambien le
sacas el parametro superpuestos, formato y dpi, algo asi:

Si queres separados, la llamas asi:

for plt, label in ftir_plot(used_oil_name_list):
plt.savefig(os.path.join(INIT_DIR, 'ftir_{}.{}'.format(label,
formato)), dpi=dpi)
plt.close()

Si queres superpuestos:

for plt, _ in ftir_plot(used_oil_name_list):
pass
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)), dpi=dpi)
plt.close()
Post by Luis Andraschnik
Hola gente!
Tengo esta función que toma como argumentos una lista de archivos de
espectros y grafica según los valores de los parámetros en un archivo único
(superpuestos) o separados en archivos individuales. A fin de no repetir
código lo hago en una única función y sólo cambia el final. El cambio es
muy sutil, la posición del if define si se cierra el plot y se guarda el
arhchivo. y sólo cambia qué nombre le asigno a/los archivo/s. Me parece que
falta claridad, un error de indentado me cambia el resultado.
Cómo de puede refactorizar para que quede más claro?
Se puede utilizar el patrón de diseño Template? Cómo?
Saludos
import os
import matplotlib.pyplot as plt
INIT_DIR=os.getcwd()
def ftir_plot(used_oil_name_list, formato='png', absorbancia=True,
'''Grafica espectros infrarrojos
formato : 'png','jpg', 'pdf', etc
absorbancia : True, eje Y absorbancia, False, eje Y transmitancia,
superpuestos: True, se grafica todo en un mismo archivo,
False, cada espectro en un archivo separado,
dpi: resolución en pixels por pulgada.
'''
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
espectro = cargar_espectro(used_oil)
x_range = espectro.index # Wavenumbers
y_range = espectro['abs'] # Absorbancia/Transmitancia
y_range = absorbancia_to_transmitancia(espectro['abs'])
# grafico el espectro
estilo(absorbancia)
label = name_for_legend(used_oil)
plt.plot(x_range, y_range, '-', label = label)
plt.legend(loc=0)
plt.savefig(os.path.join(INIT_DIR, 'ftir_{}.{}'.format(label,
formato)), dpi=dpi)
plt.close()
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)),
dpi=dpi)
plt.close()
_______________________________________________
Sitio web: http://www.python.org.ar/
Para administrar la lista (o desuscribirse) entrar a
http://listas.python.org.ar/listinfo/pyar
La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
Argentina - http://www.usla.org.ar
--
Sebastian Bassi
Luis Andraschnik
2018-07-09 18:48:58 UTC
Permalink
Sebastián y Mati

Acá pongo el código completo basado en el código de Mati:


http://linkode.org/#DWwOhlYE9gVC4tRce77ej5

Una de las clases (MultiplesArchivos) necesitó una corrección ya que el
archivo estaba cerrado antes de guardar, quedaba los archivos en blanco.

De los 6 métodos de la clase principal 4 son @staticmethods y uno es
__init__, otra vez me acuerdo de Jack Diederich cuando decía si una clase
tiene sólo 2 métodos y uno es init, probablemente no es una clase.
Evidentemente la lógica de mi modelo es funcional y parece medio forzado
pasarlo a OOP, aunque es un ejercicio interesante.

Voy a probar la solución de Sebastián después les comento

Saludos y gracias por los aportes!
Luis
Post by Sebastian Bassi
No sé que es mejor, pero si queres evitar esos 2 if que tenes ahi, podes
poner un
yield (plt, label)
antes del if not superpuestos (y borrar ese if porque la parte de
asi haces un generador en lugar de una funcion y el hecho de grabar 1 o
multiples juntos lo decidis por afuera, al momento de llamarla, tambien le
plt.savefig(os.path.join(INIT_DIR, 'ftir_{}.{}'.format(label,
formato)), dpi=dpi)
plt.close()
pass
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)), dpi=dpi)
plt.close()
On Mon, Jul 9, 2018 at 8:51 AM Luis Andraschnik <
Post by Luis Andraschnik
Hola gente!
Tengo esta función que toma como argumentos una lista de archivos de
espectros y grafica según los valores de los parámetros en un archivo único
(superpuestos) o separados en archivos individuales. A fin de no repetir
código lo hago en una única función y sólo cambia el final. El cambio es
muy sutil, la posición del if define si se cierra el plot y se guarda el
arhchivo. y sólo cambia qué nombre le asigno a/los archivo/s. Me parece que
falta claridad, un error de indentado me cambia el resultado.
Cómo de puede refactorizar para que quede más claro?
Se puede utilizar el patrón de diseño Template? Cómo?
Saludos
import os
import matplotlib.pyplot as plt
INIT_DIR=os.getcwd()
def ftir_plot(used_oil_name_list, formato='png', absorbancia=True,
'''Grafica espectros infrarrojos
formato : 'png','jpg', 'pdf', etc
absorbancia : True, eje Y absorbancia, False, eje Y transmitancia,
superpuestos: True, se grafica todo en un mismo archivo,
False, cada espectro en un archivo separado,
dpi: resolución en pixels por pulgada.
'''
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
espectro = cargar_espectro(used_oil)
x_range = espectro.index # Wavenumbers
y_range = espectro['abs'] # Absorbancia/Transmitancia
y_range = absorbancia_to_transmitancia(espectro['abs'])
# grafico el espectro
estilo(absorbancia)
label = name_for_legend(used_oil)
plt.plot(x_range, y_range, '-', label = label)
plt.legend(loc=0)
plt.savefig(os.path.join(INIT_DIR,
'ftir_{}.{}'.format(label, formato)), dpi=dpi)
plt.close()
plt.savefig(os.path.join(INIT_DIR,'ftir_.{}'.format(formato)), dpi=dpi)
plt.close()
_______________________________________________
Sitio web: http://www.python.org.ar/
Para administrar la lista (o desuscribirse) entrar a
http://listas.python.org.ar/listinfo/pyar
La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
Argentina - http://www.usla.org.ar
--
Sebastian Bassi
_______________________________________________
Sitio web: http://www.python.org.ar/
Para administrar la lista (o desuscribirse) entrar a
http://listas.python.org.ar/listinfo/pyar
La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
Argentina - http://www.usla.org.ar
Loading...