Mejorar este código
Arnau Sanchez
pyarnau en gmail.com
Jue Mayo 8 20:32:06 CEST 2008
eber_ramirez en ltv.org.mx escribió:
> Este es el primer programa que hago en Python, así que agradeceré sugerencias para mejorar el código.
>
Pues está muy bien para ser tu primera aproximación al lenguaje.
Ya que los pides, aquí van algunos comentarios (la mayoría bastante
establecidos en la "tradición", otros puramente personales):
> # Version 0.1
> # Miercoles 7 de mayo de 2008
> # gerberito en gmail.com
>
En vez de comentarios, deberías usar las docstring del módulo:
"""
Programa XYZ: Hace esto y lo otro
...
"""
> from Tkinter import *
>
Es muy común importar los módulos de tkinter de este modo, pero el
principio general es no hacer "from xyz import *", ya que ensucia el
espacio de nombres. Podrías hacer esto:
import Tkinter as tk
tk.Button(...)
> #Creamos la clase que es la base del programa
> class Calcula_MR:
> def __init__(self):
> self.CreaObjetos()
>
> def CreaObjetos(self):
> self.programa = Tk( ) # 'Ventana principal' de Tkinter's
>
Las funciones vacías no deberían llevar espacio en los paréntesis: Tk()
> self.programa.title ('Momento Resistente - Sin acero a compresion')
No dejes un espacio entre la función y el paréntesis
self.programa.title(...)
> #MarcoPrincipal=Frame(self.programa)
>
> #Primero creamos el cuadro de dialogo para introducir datos.
> # FR = Factor de reduccion, por default 0.9
> # b = ancho de la seccion en cm
> # d = peralte efectivo de la seccion en cm
> # f'c = resistencia del concreto a la compresion a los 28 dias en kg/cm2
> # fy = Limite de fluencia del acero en kg/cm2
> # As = Area de acero en tension en cm2
>
Como antes: estos comentarios van en los docstrings del método/función.
De esta forma tu aplicación quedará perfectamente documentada.
> # Ahora creamos las zonas donde el usuario introduce datos
>
> # Primero ponemos las etiquetas de los datos que ocuparemos
> fila = 1
> for label in 'FR ', 'b ', 'd ', 'fc ', 'fy ', 'As ':
> Etiqueta=Label(self.programa, text=label+'=', borderwidth=6)
> Etiqueta.grid(row=fila,column=0)
> #Label(self.programa,text=label+'=', borderwidth=6).grid(row=fila, column=0)
> fila = fila + 1
>
Ese uso de "fila" es sospechoso. Usa enumerate:
for fila, label in ("label1", "label2"):
# fila empieza a contar por 0
Ver de paso Idiomatic Python:
http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
> #Ahora las unidades en las que se trabaja
> fila = 1
> for label in ' ', 'cm ', 'cm ', 'kg/cm2 ', 'kg/cm2 ', 'cm2 ':
> Etiqueta=Label(self.programa, text=label, borderwidth=6)
> Etiqueta.grid(row=fila,column=2)
> #Label(self.programa,text=label, borderwidth=6).grid(row=fila, column=2)
> fila = fila + 1
>
Está claro que los nombres y las unidades van unidas, ¿por qué hacer dos
bucles? puedes hacer
for index, (label, unit) in enumerate([("label1", "unit1"), (....)]):
o si quieres manter dos arrays separados, usa zip:
for index, (label, unit) in enumerate(zip(labels, units)):
> self.FR_t=StringVar()
> Entry(self.programa, width=10, textvariable=self.FR_t).grid(row=1, column=1)
> self.FR_t.set('0.9')
>
> self.b_t=StringVar()
> Entry(self.programa, width=10, textvariable=self.b_t).grid(row=2, column=1)
> self.b_t.set('20')
>
> self.d_t=StringVar()
> Entry(self.programa, width=10, textvariable=self.d_t).grid(row=3, column=1)
> self.d_t.set('40')
>
Aquí hay un patrón muy claro, deberías crear una lista e iterar en un bucle.
Quizá tengas algún problema al asignar la variable a self, ya que
tendrás el nombre de la variable en una cadena: dale un vistazo a
setattr. Otro tema sería que, en vez de meter esas variables
directamente en la instancia, crearas otra, para separar un poco las cosas:
class Container:
pass
variables = Container()
variables.d_t = 3
ó si tenemos el nombre de variable en una cadena... s = "d_t", hacemos:
setattr(variables, s, 3)
En este caso puedes acceder a las variables (como cadena) y su valor
pidiendo con "vars" el diccionario de la clase:
vars(variables)
También podrías meterla directamente en un diccionario, pero es
discutible si es estético:
variables["d_t"]
> def Calculos(self):
> #Extraemos los datos de los "entry's"
> FR=float(self.FR_t.get())
> b=float(self.b_t.get())
> d=float(self.d_t.get())
> fc=float(self.fc_t.get())
> fy=float(self.fy_t.get())
> As=float(self.As_t.get())
>
Mucha repetición: puedes abstraerlo en un bucle.
---
Esto en cuanto a lo que atañe al uso del lenguaje. Como concepto general
te recomendaría modularizar: separa la lógica de la presentación
(frontend). Si alguien quiere usar tu script (la parte de cálculo) desde
el suyo propio , o cambiar a gtk, por ejemplo, tendrá que retocarlo
bastante, ya que la interacción con Tk está por todas partes.
A este respecto, y uses el sistema operativo que uses, no dejes de darle
un vistazo a este repaso de la filosofía UNIX:
http://www.faqs.org/docs/artu/ch01s06.html
_______________________________________________
Lista de correo Python-es
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes
Más información sobre la lista de distribución Python-es