> Manuales > Python
|
|
|
|
|
Capítulo 4 Estudio de caso: diseño de una interfaz4.1 TurtleWorldPara acompañar este libro, he escrito un conjunto de módulos llamados Puede descargar >>> from TurtleWorld import * Esta es una variación de la declaración >>> TurtleWorld() Una ventana aparecerá en la pantalla y el intérprete debería mostrar algo como esto: Los delimitadores angulares (es decir, "<" y ">") indican que el valor de retorno de Para crear una tortuga, escribe: >>> juan = Turtle() En este caso, le asignamos el valor de retorno de Las funciones de dirección de la tortuga son fd y bk para ir hacia adelante y hacia atrás, y lt y rt para moverse hacia la izquierda y hacia la derecha. Para dibujar un ángulo recto, escribe: >>> fd (juan, 100) >>> lt (juan) >>> fd (juan, 100) La primera línea (y tercera) le dice Antes de continuar, usa 4.2 Simple repeticiónSi aún no lo has hecho, entra en el directorio que contiene from TurtleWorld import * TurtleWorld () juan = Turtle () fd (juan, 100) lt (juan) fd (juan, 100) Cuando ejecutes el programa, deberías ver a wait_for_user() al final del programa, y ejecútalo de nuevo. Ahora, la ventana permanecerá hasta que la cierres. Ahora modifica el programa para dibujar un cuadrado. ¡Y no sigas leyendo hasta que tu programa funcione! Es muy probable que hayas escrito algo como esto (olvidándonos del código que crea TurtleWorld y espera a que el usuario interactúe): fd (juan, 100) lt (Bob) fd (juan, 100) lt (Bob) fd (juan, 100) lt (Bob) fd (juan, 100) Podemos hacer lo mismo con una declaración más concisa. Añade este ejemplo a for i in range(4):
print "¡Hola!"
Deberías ver algo como esto: ¡Hola! ¡Hola! ¡Hola! ¡Hola! Este es el uso más simple de la declaración He aquí una instrucción for i in range(4):
fd (juan, 100)
lt (juan)
La sintaxis de una instrucción A veces se llama bucle (o loop) a la instrucción Esta versión es en realidad un poco diferente del anterior código para dibujar un cuadrado, porque hace un último giro a la izquierda después de dibujar el último lado del cuadrado. Este giro de más emplea algo de tiempo, pero simplifica el código, ya que hacemos exactamente lo mismo en cada iteración del bucle. Otro efecto de esta versión es dejar a la tortuga en la posición inicial mirando en la dirección inicial. 4.3 EjerciciosLa siguiente serie de ejercicios utiliza TurtleWorld. Los ejercicios tienen el propósito de divertir, pero también tienen su puntillo. Mientras trabajes con ellos, piensa en ese puntillo. En las próximas secciones encontrarás las soluciones a los ejercicios; no mires las soluciones hasta completar los ejercicios (o al menos hasta haberlo intentado).
4.4 EncapsulaciónEl primer ejercicio pide meter en una definición de función el código para dibujar un cuadrado y llamar a esta función, pasando la tortuga como argumento. Aquí está la solución: def square(t):
for i in range(4):
fd(t, 100)
lt(t)
square(juan)
Las instrucciones que encontramos en el interior de la función, Dentro de la función, square(juan) pepe = Turtle() square(pepe) Encerrar un porción de código en una función se llama "encapsular". Una de las ventajas de la encapsulación es que asigna un nombre al código, lo cual no deja de ser una forma de documentarlo, es decir, de explicar para qué sirve. Otra ventaja es que permite reutilizar el código sin necesidad de copiarlo, sino, sencillamente, realizando una segunda llamada a la función. 4.5 GeneralizaciónEl siguiente paso consiste en añadir un parámetrolenght a square. Aquí está la solución:
def square(t, length):
for i in range(4):
fd(t, length)
lt(t)
square(juan, 100)
La adición de un parámetro a una función se llama "generalización", ya que (perdón por la obviedad) hace a la función más general: en la versión anterior, el cuadrado es siempre del mismo tamaño; en la nueva versión, el cuadrado puede ser de cualquier tamaño. El siguiente paso es también una generalización. En lugar de dibujar cuadrados, def polygon(t, length, n):
angle = 360.0 / n
for i in range(n):
fd(t, length)
lt(t, angle)
polygon(bob, 70, 7)
Este código dibuja un polígono de 7 lados de longitud 70. Si la llamada a la función tiene más de un par de argumentos numéricos, es fácil olvidar qué significa cada uno de ellos, o en qué orden hay que escribirlos. Es válido, y a veces útil, incluir los nombres de los parámetros en la lista de argumento s:polygon(bob, length=70, n=7) Esta sintaxis hace que el programa se lea con mayor facilidad. Nos recuerda también como funcionan los argumentos y los parámetros: al llamar a una función, los argumentos se asignan a los parámetros. 4,6 Diseño de la intefazEl siguiente paso consiste en programar Una manera de hacerlo es copiar y modificar def circle(t, r):
circumference = 2 * math.pi * r
n = 50
length = circumference / n
polygon(t, length, n)
La primera línea calcula la circunferencia de un círculo con radio r usando la fórmula 2 π r. Puesto que usmos
Una limitación de esta solución es que n es una constante, lo cual significa que para círculos muy grandes, los segmentos serán demasiado largos, y para los círculos pequeños, perderemos mucho tiempo dibujando segmentos demasiado pequeños. Una solución consistiría en generalizar la función tomando La interfaz de una función es un resumen de cómo se utiliza: cuáles son los parámetros, qué hace la función de hacer y cuál es el valor de retorno. Una interfaz es "clara" (o "limpia"), si es "tan simple como sea posible, pero no más" (Einstein). En este ejemplo, En lugar de recargar la interfaz, es mejor subordinar el valor de def circle(t, r):
circumference = 2 * math.pi * r
n = int(circumference / 4)
length = circumference / n
polygon(t, length, n)
Ahora el número de segmentos es (aproximadamente) 4,7 RefactorizaciónAl escribir el código de Una alternativa sería empezar con una copia del def arc(t, r, angle):
arclength = 2 * math.pi * r * angle / 360
n = int(arclength / 4)
length = arclength / n
step_angle = angle / n
for i in range(n):
fd(t, length)
lt(t, step_angle))
La segunda mitad de esta función se parece a def polyline(t, length, n, angle):
for i in range(n):
fd(t, length)
lt(t, angle)
Ahora podemos reescribir def polygon(t, length, n):
angle = 360.0 / n
polyline(t, length, n, angle)
def arc(t, r, angle):
arclength = 2 * math.pi * r * angle / 360
n = int(arclength / 4)
length = arclength / n
polyline(t, length, n, angle/n)
Por último, podemos reescribir def circle(t, r):
arc(t, r, 360.0))
Este proceso de reorganización del código de un programa para mejorar las interfaces de las funciones y facilitar la reutilización de código, se llama refactorización. En este caso, hemos observado que hay similitudes entre el código de Si haberlo planeado antes, podríamos haber escrito 4.8 Un plan de desarrolloUn plan de desarrollo es un proceso para escribir programas. El proceso que hemos utilizado en este caso es lo que llamamos EGR, siglas de "encapsulación, generalización y refactorización". Las pasos delEGR son:
El EGR tiene algunos inconvenientes (presentaremos alternativas más adelante), pero puede ser útil si no sabe de antemano cómo dividir el programa en funciones. Este enfoque permite diseñar a medida que se avanza. 4.9 docstringUn docstring es una cadena al principio de una función que explica la interfaz ("doc" es la abreviatura de "documentación"). He aquí un ejemplo: def polyline(t, length, n, angle):
"""Dibuja n segmentos de longitud (length) dada y
un ángulo entre ellos (angle) expresado en grados. t is una tortuga.
"""
for i in range(n):
fd(t, length)
lt(t, angle)
Este docstring es una cadena con triples comillas, también conocida como una cadena de múltiples líneas, porque las triples comillas permiten a la cadena abarcar más de una línea. Es sencillo, pero contiene la información esencial necesaria para utilizar la función. En él se explican concisamente qué necesita la función para hacer su trabajo (sin entrar en los detalles sobre cómo lo hace). Explica qué efecto tiene cada parámetro en el comportamiento de la función y el tipo de cada parámetro (siempre que no sea evidente). Generar este tipo de documentación es una parte importante del diseño de interfaces. Una interfaz bien diseñada debe ser fácil de explicar; si existen dificultades para explicar una de las funciones, es muy probablemente que la función sea susceptible de mejora. 4.10 Glosarioinstancia: un miembro de un conjunto. La TurtleWorld de este capítulo es miembro del conjunto de TurtleWorlds. bucle: un declaración compuesta cuyo cuerpo puede ser ejecutado más de una vez. encapsulación: el proceso de transformación de una secuencia de declaraciones en una definición de función. generalización: el proceso de sustitución de algo innecesariamente específico (como un número) por algo adecuadamente general (como una variable o un parámetro). interfaz: una descripción de cómo usar una función, incluyendo el nombre, la descripción de los argumentos y el valor de retorno. plan de desarrollo: un proceso para escribir program as.docstring: una cadena que aparece en la definición de una función, cuyo propósito es documentar la interfaz de la función. 4.11 Ejercicios
|
|
