\subsection{Funciones}
	\subsubsection{Definiendo funciones}
		\begin{itemize}
			\item Para definir una función: def nombre(parametros):
			\begin{verbatim}
				>>> def saluda():
				...   print "hola"
				...
				>>> saluda()
				hola
				>>> 
			\end{verbatim}
			\item El paso de parámetros es, al igual que en Java, siempre por valor:
			\subitem Lo que ocurre es que en el caso de instancias, pasamos por valor una referencia
			\begin{verbatim}
				>>> class A:
				...   def __init__(self):
				...     self.valor = 0
				...   def modificar(self):
				...     self.valor += 1
				...
				>>> a = A()
				>>> def f(a): #Pasamos por valor la referencia
				...   a.modificar() #Al ser una referencia, se modifica
				...   a = None #Pero esto sólo afecta al bloque de la función
				...
				>>> f(a)
				>>> a.valor
				1
				>>> a is None
				False
				>>>
			\end{verbatim}
		\end{itemize}
	\subsubsection{Parámetros por defecto}
		\begin{itemize}
			\item Permite no tener que escribir todos los campos
			\begin{verbatim}
				>>> def dimeDosNumeros(x=5,y=10):
				...   print x,y
				...
				>>> dimeDosNumeros()
				5 10
				>>> dimeDosNumeros(10)
				10 10
				>>> dimeDosNumeros(10,15)
				10 15
				>>> dimeDosNumeros(y=15)
				5 15
				>>> dimeDosNumeros(x=10,y=15)
				10 15
			\end{verbatim}
			\item El que se puedan llamar sólo a los campos que se desee hace que en Python no haya sobrecarga de operaciones
			\begin{verbatim}
				>>> def f():
				...   print "hola"
				...
				>>> def f(a): #Sobreescribe la función anterior
				...   print a
				...
				>>> f(5)
				5
				>>> f() #Ya no existe
				Traceback (most recent call last):
				  File "<stdin>", line 1, in ?
				NameError: name 'f' is not defined
			\end{verbatim}
			\item Si se puede modificar y se modifica el valor de los parámetros por defecto, en las siguientes funciones valdrá el valor modificado:
			\begin{verbatim}
				>>> def f(lista=[]):
				...   lista.append('hola')
				...   print lista
				...
				>>> f()
				['hola']
				>>> f()
				['hola','hola']
				>>> def f(lista=None):
				...   if lista is None:
				...     lista = ['hola']
				...   print lista
				...
				>>> f()
				['hola']
				>>> f()
				['hola']
			\end{verbatim}
		\end{itemize}
	\subsubsection{Lista de argumentos variable}
		\begin{verbatim}
			>>> def f(par1,par2,*pars,**parsClave):
			...  print par1
			...  print par2
			...  print pars
			...  print parsClave
			...
			>>> f(1,2,3,4,nombre='hola',apellido='adios')
			1
			2
			[3,4]
			{nombre:'hola',apellido:'adios'}
			>>> 
		\end{verbatim}
	\subsubsection{Retorno}
		\begin{itemize}
			\item Para devolver valores, se utiliza la palabra \verb+return+. Pueden devolverse múltiples valores
			\begin{verbatim}
				>>> def f():
				...   return 5,"hola"
				...
				>>> a,b = f()
				>>> a
				5
				>>> b
				'hola'
			\end{verbatim}
		\end{itemize}
	\subsubsection{Variables globales}
		\begin{itemize}
			\item Para acceder en modo escritura a variables globales se utiliza la palabra \verb+global+:
			\begin{verbatim}
				>>> a = 7
				>>> def f():
				...   print a #Accede pero en modo lectura
				...
				>>> def f2():
				...   a=9 #Está creando una nueva variable
				...   print a
				...
				>>> def f3():
				...   global a #Trabajamos con la global
				...   a = 9 
				...   print a
				...
				>>> def f4():
				...   print a #Imprimimos la global?
				...   a = 4 #Y creamos una nueva?
				...
				>>> f()
				7
				>>> a
				7
				>>> f2()
				9
				>>> a
				7
				>>> f3()
				9
				>>> a
				9
				>>> f4() #No: se adelanta a nivel de función y ve el conflicto
				Traceback (most recent call last):
				  File "<stdin>", line 1, in ?
				  File "<stdin>", line 2, in f4
				UnboundLocalError: local variable 'a' referenced before assignment
				>>>
			\end{verbatim}
		\end{itemize}
\newpage
\subsection{Clases}
	\subsubsection{Definiendo clases}
		\begin{itemize}
			\item Una clase se define con \verb+class NombreClase+ y sus métodos, atributos y documentación en el bloque
			\item Los métodos reciben un primer argumento \verb+self+, que es la propia instancia desde la que se invoca el método, seguida del resto de parámetros (en caso de que haya)
			\item Hay una serie de métodos especiales que empiezan y terminan por \verb+__+ que comentaremos más tarde. Por ejemplo, el constructor es el método \verb+__init__+
			\item Para crear variables de la instancia, basta llamar a \verb+self.variable = algo+
			\item Ejemplo de definición de clase:
			\begin{verbatim}
				>>> class A:
				...   variableDeClase=0 #similar a variable estática
				...   def __init__(self,parametro): #Constructor
				...     self.nombre = parametro
				...     A.variableDeClase += 1
				...   def getNombre(self):
				...     return self.nombre
				...   def setNombre(self,nombre):
				...     self.nombre = nombre
				...   def getNumeroInstancias(self):
				...     return A.variableDeClase
				...
				>>>
			\end{verbatim}
			\item Para crear una instancia, basta con llamar al constructor tal que: 
				\subitem \verb+instancia = nombreclase(parametros)+
			\item Luego se llama a los métodos normalmente
			\item Ejemplo:
			\begin{verbatim}
				>>> a = A('hola')
				>>> a.getNombre()
				'hola'
				>>> a.setNombre('adios')
				>>> a.getNombre()
				'adios'
				>>> a.getNumeroInstancias()
				1
				>>> A(0);A(0);A(0)
				>>> a.getNumeroInstancias()
				4
				>>>
			\end{verbatim}
		\end{itemize}
	
	\subsubsection{Herencia}
		\begin{itemize}
			\item Para que una clase herede de otra, basta con definirlo en la definición de la clase tal que:\\
			\verb+class Hija(Padre):+
			\item Python permite herencia múltiple, de manera que una clase puede heredar de varias
			\begin{verbatim}
				>>> class Padre:
				...   def __init__(self):
				...     print "Soy una instancia de la clase Padre"
				...   def metodoA(self):
				...     print "Llamando al método A de la clase Padre"
				...
				>>> class Madre:
				...   def __init__(self):
				...     print "Soy una instancia de la clase Madre"
				...   def metodoB(self):
				...     print "Llamando al método B de la clase Madre"
				...
				>>> class Hija(Padre,Madre):
				...   def __init__(self):
				...     Padre.__init__(self)
				...     Madre.__init__(self)
				... 
				>>> a = Hija()
				Soy una instancia de la clase Padre
				Soy una instancia de la clase Madre
				>>> a.metodoA()
				Llamando al método A de la clase Padre
				>>> a.metodoB()
				Llamando al método B de la clase Madre
				>>> isinstance(a,Padre)
				True
				>>> isinstance(a,Madre)
				True
				>>> isinstance(a,Hija)
				True
				>>> isinstance(a,str)
				False
				>>> issubclass(Hija,Padre)
				True
				>>> issubclass(Hija,Madre)
				True
				>>> issubclass(Hija,str)
				False
			\end{verbatim}
		\end{itemize}
	\subsubsection{Polimorfismo}
		\begin{itemize}
			\item Dadas B y C hijas de A, llamamos al método heredado \verb+imprimeNombre+
			\begin{verbatim}
				>>> class A:
				...   def __init__(self,nombre):
				...     self.nombre=nombre
				...   def imprimeNombre(self):
				...     print "El nombre es:",selfnombre
				...
				>>> class B(A):
				...   def __init__(self,nombre,apellido):
				...     A.__init__(self,nombre)
				...     self.apellido = apellido
				...
				>>> class C(A):
				...   def __init__(self,nombre,apellidos):
				...     A.__init__(self,nombre)
				...     self.apellido = apellidos[0]
				...     self.apellido2 = apellidos[1]
				...
				>>> b = B('Nombre','Apellido')
				>>> c = C('Nombrecillo',('Apellido','Apellido2'))
				>>> a = [b,c]
				>>> for i in a:
				...   i.imprimeNombre()
				...
				Nombre
				Nombrecillo
				>>>
			\end{verbatim}
			\item Dado que Python es un lenguaje de tipado dinámico, la herencia no es estrictamente necesaria para utilizar polimorfismo
			\begin{verbatim}
				>>> class B:
				...   def __init__(self,nombre,apellido):
				...     self.nombre = nombre
				...     self.apellido = apellido
				...   def imprimeNombre(self):
				...     print "El nombre es:",self.nombre
				...
				>>> class C:
				...   def __init__(self,nombre,apellidos):
				...     self.nombre = nombre
				...     self.apellido = apellidos[0]
				...     self.apellido2 = apellidos[1]
				...   def imprimeNombre(self):
				...     print "El nombre es:",self.nombre
				...
				>>> b = B('Nombre','Apellido')
				>>> c = C('Nombrecillo',('Apellido','Apellido2'))
				>>> a = [b,c]
				>>> for i in a:
				...   print i.imprimeNombre()
				...
				Nombre
				Nombrecillo
				>>>
			\end{verbatim}
		\end{itemize}

\newpage
\subsection{Excepciones}
	\subsubsection{Ejemplos de excepción}
		\begin{verbatim}
			>>> a
			Traceback (most recent call last):
			  File "<stdin>", line 1, in ?
			NameError: name 'a' is not defined
			>>> a = None
			>>> a.metodo()
			Traceback (most recent call last):
  			  File "<stdin>", line 1, in ?
			AttributeError: 'NoneType' object has no attribute 'metodo'
		\end{verbatim}
	\subsubsection{Capturando excepciones}
		\begin{itemize}
			\item try ... except
			\begin{itemize}
				\item Con \verb+except Clase,instancia:+ se capturan las excepciones que sean instancia de la clase \verb+Clase+ o hijas de ella
				\begin{verbatim}
					>>> try:
					...   a
					... except NameError, ne:
					...   print "Te pillé"
					...   print ne
					...
					Te pillé
					name 'a' is not defined
					>>> try:
					...   a
					... except Exception, e:
					...   print "Te pillé de manera más genérica"
					...   print e
					...
					Te pillé de manera más genérica
					name 'a' is not defined
					>>>
				\end{verbatim}
				\item Con \verb+except:+ se capturan todas las excepciones
				\begin{verbatim}
					>>> try:
					...   5/0
					... except NameError, ne:
					...   print "Te pillé"
					... except:
					...   print "No sé quién eres, pero también te pillé"
					No sé quién eres, pero también te pillé
					>>>
				\end{verbatim}
			\end{itemize}
			\item try ... finally
			\begin{itemize}
				\item No captura ninguna excepción, pero se asegura de que algo ocurre
				\begin{verbatim}
					>>> import threading
					>>> bloqueador = threading.Lock()
					>>> bloqueador.acquire()
					>>> try:
					...   5/0
					... finally:
					...   bloqueador.release() #No nos la podemos jugar
					Traceback (most recent call last):
					  File "<stdin>", line 2, in ?
					ZeroDivisionError: integer division or modulo by zero
					>>> bloqueador.locked()
					False
				\end{verbatim}
				\item A diferencia de otros lenguajes, no existe try...except...finally
			\end{itemize}
		\end{itemize}
	\subsubsection{Lanzando excepciones}
		\begin{itemize}
			\item Para lanzar una excepción se utiliza la palabra reservada \verb+raise+
			\begin{verbatim}
				>>> class A: pass
				...
				>>> try:
				...   raise A()
				... except A,a:
				...   print ":)"
				...
				:)
				>>> try:
				...   raise A
				... except A,a:
				...   print ":-o"
				...
				:-o
				>>> raise "mooolaaa"
				Traceback (most recent call last):
				  File "<stdin>", line 1, in ?
				mooolaaa
			\end{verbatim}
			\item Se puede lanzar cualquier instancia de cualquier clase, instancia o string (deprecado)
		\end{itemize}
\subsection{Ejercicio}
	\subsubsection{Implementando código en Python}
		\begin{itemize}
			\item Como ejemplo de la facilidad y claridad de Python
			\item Python: el \emph{pseudocódigo ejecutable}
		\end{itemize}
	\subsubsection{Rabin-Miller}
		\begin{itemize}
			\item El algoritmo de Rabin-Miller permite, dado un número, saber si es primo.
			\item En realidad, sólo asegura que \emph{no} es primo cuando lo sabe con certeza. En caso de dar afirmativo, hay un 50\% de probabilidades de que lo sea
			\item Ejecutado varias veces, las probabilidades de que lo sea incrementan sustancialmente
		\end{itemize}
	\subsubsection{Implementación}
		\begin{itemize}
			\item Descargar el libro \href{http://www.telefonica.net/web2/lcripto/lcripto.html}{Criptografía y Seguridad en Computadores} de la página web de \href{http://wwwdi.ujaen.es/~mlucena/}{Manuel José Lucena López}
			\item En la 4ª Edición (Versión 0.6.2), el algoritmo está explicado en el punto 5.7.2, página 83.
		\end{itemize}
\newpage
