Next Up Previous Hi Index

Chapter 13

Clases y funciones

13.1 Hora

Como otro ejemplo de un tipo definido por el usuario, definiremos una clase llamada Hora que registra la hora del d�a. La definici�n de la clase es como sigue:

class Hora:
  pass

Podemos crear un nuevo objeto Hora y asignar atributos para contener las horas, minutos y segundos:

hora = Hora()
hora.horas = 11
hora.minutos = 59
hora.segundos = 30

El diagrama de estado del objeto Hora es as�:

A modo de ejercicio, escriba una funci�n imprimeHora que acepte un objeto Hora como argumento y lo imprima en el formato horas:minutos:segundos.
Como un segundo ejercicio, escriba una funci�n booleana despues que tome dos objetos Hora, t1 y t2, como argumentos y devuelva verdadero (1) si t1 sigue cronol�gicamente a t2 y falso (0) en caso contrario.

13.2 Funciones puras

En las pr�ximas secciones, escribiremos dos versiones de una funci�n llamada sumaHora que calcule la suma de dos Horas. Mostrar�n dos tipos de funciones: funciones puras y modificadores.

�ste es un esbozo de sumaHora:

def sumaHora(t1, t2):
  suma = Hora()
  suma.horas = t1.horas + t2.horas
  suma.minutos = t1.minutos + t2.minutos
  suma.segundos = t1.segundos + t2.segundos
  return suma

La funci�n crea un nuevo objeto Hora, inicializa sus atributos y devuelve una referencia al nuevo objeto. A esto se le llama funci�n pura porque no modifica ninguno de los objetos que se le pasan y no tiene efectos laterales, como mostrar un valor o tomar una entrada del usuario.

Aqu� tiene un ejemplo de c�mo usar esta funci�n. Crearemos dos objetos Hora: horaActual, que contiene la hora actual, y horaPan, que contiene la cantidad de tiempo que necesita un panadero para hacer pan. Luego usaremos sumaHora para averiguar cu�ndo estar� hecho el pan. Si a�n no ha terminado de escribir imprimeHora, eche un vistazo a la Secci�n 14.2 antes de probar esto:

>>> horaActual = Hora()
>>> horaActual.horas = 9
>>> horaActual.minutos = 14
>>> horaActual.segundos =  30

>>> horaPan = Hora()
>>> horaPan.horas =  3
>>> horaPan.minutos =  35
>>> horaPan.segundos =  0

>>> horaHecho = sumaHora(horaActual, horaPan)
>>> imprimeHora(horaHecho)

La salida de este programa es 12:49:30, lo que es correcto. Por otra parte, hay casos en los que el resultado no es correcto. �Puede imaginar uno?

El problema es que esta funci�n no trata los casos en los que el n�mero de segundos o minutos suma m�s que sesenta. Cuando ocurre eso, debemos "llevar" los segundos sobrantes a la columna de los minutos o los minutos extras a la columna de las horas.

He aqu� una versi�n corregida de la funci�n:

def sumaHora(t1, t2):
  suma = Hora()
  suma.horas = t1.horas + t2.horas
  suma.minutos = t1.minutos + t2.minutos
  suma.segundos = t1.segundos + t2.segundos

  if suma.segundos >= 60:
    suma.segundos = suma.segundos - 60
    suma.minutos = suma.minutos + 1

  if suma.minutos >= 60:
    suma.minutos = suma.minutos - 60
    suma.horas = suma.horas + 1

  return suma

Aunque esta funci�n es correcta, empieza a ser grande. M�s adelante sugeriremos una aproximaci�n alternativa que nos dar� un c�digo m�s corto.

13.3 Modificadores

Hay veces en las que es �til que una funci�n modifique uno o m�s de los objetos que recibe como par�metros. Normalmente, el llamante conserva una referencia a los objetos que pasa, as� que cualquier cambio que la funci�n haga ser� visible para el llamante. Las funciones que trabajan as� se llaman modificadores.

incremento, que a�ade un n�mero dado de segundos a un objeto Hora, se escribir�a de forma natural como un modificador. Un esbozo r�pido de la funci�n podr�a ser �ste:

def incremento(hora, segundos):
  hora.segundos = hora.segundos + segundos

  if hora.segundos >= 60:
    hora.segundos = hora.segundos - 60
    hora.minutos = hora.minutos + 1

  if hora.minutos >= 60:
    hora.minutos = hora.minutos - 60
    hora.horas = hroa.horas + 1

La primera l�nea realiza la operaci�n b�sica, las restantes tratan con los casos especiales que vimos antes.

�Es correcta esta funci�n? �Qu� ocurre si el par�metro segundos es mucho mayor que sesenta? En tal caso, no es suficiente con acarrear una vez; debemos seguir haci�ndolo hasta que segundos sea menor que sesenta. Una soluci�n es sustituir las sentencias if por sentencias while:

def incremento(hora, segundos):
  hora.segundos = hora.segundos + segundos

  while hora.segundos >= 60:
    hora.segundos = hora.segundos - 60
    hora.minutos = hora.minutos + 1

  while hora.minutos >= 60:
    hora.minutos = hora.minutos - 60
    hora.horas = hroa.horas + 1

Ahora esta funci�n es correcta, pero no es la soluci�n m�s eficiente.

Como ejercicio, reescriba esta funci�n de modo que no contenga tantos bucles.
Como un segundo ejercicio, reescriba incremento como una funci�n pura, y escriba una funci�n que llame a ambas versiones.

13.4 �Qu� es mejor?

Todo lo que se pueda hacer con modificadores puede hacerse tambi�n con funciones puras. En realidad, algunos lenguajes de programaci�n s�lo permiten funciones puras. Hay ciertas evidencias de que los programas que usan funciones puras son m�s r�pidos de desarrollar y menos propensos a los errores que los programas que usan modificadores. Sin embargo, a veces los modificadores son �tiles, y en algunos casos los programas funcionales son menos eficientes.

En general, recomendamos que escriba funciones puras siempre que sea razonable hacerlo as� y recurra a los modificadores s�lo si hay una ventaja convincente. Este enfoque podr�a llamarse estilo funcional de programaci�n.

13.5 Desarrollo de prototipos frente a planificaci�n

En este cap�tulo mostramos una aproximaci�n al desarrollo de programas a la que llamamos desarrollo de prototipos. En cada caso, escribimos un esbozo basto (o prototipo) que realizaba el c�lculo b�sico y luego lo probamos sobre unos cuantos casos, corrigiendo los fallos tal como los encontr�bamos.

Aunque este enfoque puede ser efecitvo, puede conducirnos a c�digo que es innecesariamente complicado, ya que trata con muchos casos especiales, y poco fiable, porque es dif�cil saber si encontr� todos los errores.

Una alternativa es el desarrollo planificado, en el que una comprensi�n del problema en profundidad puede hacer la programaci�n mucho m�s f�cil. En este caso, el enfoque es que un objeto Hora es en realidad �un n�mero de tres d�gitos en base 60! El componente segundo es la "columna de unidades", el componente minuto es la "columna de las sesententas" y el componente hora es la "columna de las tresmilseiscentenas".

Cuando escribimos sumaHora e incremento, en realidad est�bamos haciendo una suma en base 60, que es por lo que deb�amos acarrear de una columna a la siguiente.

Esta observaci�n sugiere otro enfoque para el problema. Podemos convertir un objeto Hora en un simple n�mero y sacar provecho del hecho de que la m�quina sabe la aritm�tica necesaria. La siguiente funci�n convierte un objeto Hora en un entero:

def convierteASegundos(t):
  minutos = t.horas * 60 + t.minutos
  segundos = minutos * 60 + t.segundos
  return segundos

Ahora, s�lo necesitamos una forma de convertir un entero en un objeto Hora:

def haceHora(segundos):
  hora = Hora()
  hora.horas = segundos/3600
  segundos = segundos - hora.horas * 3600
  hora.minutos = segundos/60
  segundos = segundos - hora.minutos * 60
  hora.segundos = segundos
  return hora

Puede que tenga usted que pensar un poco para convencerse de que esta t�cnica para convertir de una base a otra es correcta. Suponiendo que est� usted convencido, puede usar estas funciones para reescribir sumaHora:

def sumaHora(t1, t2):
  segundos = convierteASegundos(t1) + convierteASegundos(t2)
  return haceHora(segundos)

Esta versi�n es mucho m�s corta que la original, y es mucho m�s f�cil de demostrar que es correcta (suponiendo, como es habitual, que las funciones a las que llama son correctas).

Como ejercicio, reescriba incremento de la misma forma.

13.6 Generalizaci�n

De alg�n modo, convertir de base 60 a base 10 y de vuelta es m�s dif�cil que simplemente manejarse con las horas. La conversi�n de base es m�s abstracta; nuestra intuici�n para tratar con las horas es mejor.

Pero si tenemos la comprensi�n para tratar las horas como n�meros en base 60, y hacer la inversi�n de escribir las funciones de conversi�n (convierteASegundos y haceHora), obtenemos un programa que es m�s corto, m�s f�cil de leer y depurar y m�s fiable.

Tambi�n es m�s f�cil a�adir funcionalidades m�s tarde. Por ejemplo, imagine restar dos Horas para hallar el intervalo entre ellas. La aproximaci�n ingenua ser�a implementar la resta con acarreo. Con el uso de las funciones de conversi�n ser� m�s f�cil y con mayor probabilidad, correcto.

Ir�nicamente, a veces hacer un poblema m�s complejo (o m�s general) lo hace m�s f�cil (porque hay menos casos especiales y menos oportunidades de error).

13.7 Algoritmos

Cuando escribe una soluci�n general para una clase de problemas, en contraste con una soluci�n espec�fica a un problema concreto, ha escrito un algoritmo. Mencionamos esta palabra antes pero no la definimos con precisi�n. No es f�cil de definir, as� que probaremos un par de enfoques.

Primero, piense en algo que no es un algoritmo. Cuando usted aprendi� a multiplicar n�meros de una cifra, probablemente memoriz� la tabla de multiplicar. En efecto, memoriz� 100 soluciones espec�ficas. Ese tipo de conocimiento no es algor�tmico.

Pero si usted era "harag�n" probablemente hizo trampa aprendiendo algunos trucos. Por ejemplo, para encontrar el producto de n por 9, puede escribir n-1 como el primer d�gito y 10-n como el segundo d�gito. Este truco es una soluci�n general para multiplicar cualquier n�mero de una cifra por 9. �Eso es un algoritmo!

De forma similar, las t�cnicas que aprendi� para la suma y la resta con acarreo y la divisi�n larga son todas algoritmos. Una de las caracter�sticas de los algoritmos es que no requieren inteligencia para llevarse a cabo. Son procesos mec�nicos en los que cada paso sigue al anterior de acuerdo a un conjunto simple de reglas.

En nuestra opini�n, es un poco vergonzoso que los humanos pasen tanto tiempo en la escuela aprendiendo a ejecutar algoritmos que, de forma bastante similar, no exigen inteligencia.

Por otra parte, el proceso de dise�ar algoritmos es interesante, un desaf�o intelectual y una parte primordial de lo que llamamos programar.

Algunas de las cosas que la gente hace naturalmente, sin dificultad ni pensamiento consciente, son las m�s dif�ciles de expresar algor�tmicamente. Entender el lenguaje natural es un buen ejemplo. Todos lo hacemos, pero hasta el momento nadie ha sido capaz de explicar c�mo lo hacemos, al menos no en la forma de un algoritmo.

13.8 Glosario

funci�n pura
Una funci�n que no modifica ninguno de los objetos que recibe como par�metros. La mayor�a de las funciones puras son rentables.
modificador
Una funci�n que modifica uno o m�s de los objetos que recibe como par�metros. La mayor�a de los modificadores no entregan resultado.
estilo funcional de programaci�n
Un estilo de programaci�n en el que la mayor�a de las funciones son puras.
desarrollo de prototipos
Una forma de desarrollar programas empezando con un prototipo y prob�ndolo y mejor�ndolo gradualmente.
desarrollo planificado
Una forma de desarrollar programas que implica una comprensi�n de alto nivel del problema y m�s planificaci�n que desarrollo incremental o desarrollo de prototipos.
algoritmo
Un conjunto de instrucciones para solucionar una clase de problemas por medio de un proceso mec�nico sin intervenci�n de inteligencia.


Next Up Previous Hi Index

" + str + "

Close window

Hosted by www.Geocities.ws

"); } //-->
Hosted by www.Geocities.ws

1