diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2013-08-23 03:56:40 (GMT) |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2013-08-23 03:56:40 (GMT) |
commit | e4d030ee6eedde4eb0322469d542437e539cdb39 (patch) | |
tree | feb77fd5ab0de7242d6ef4ab6005a9489213fc18 | |
parent | 77f06d4b7c4c069482cbab607ab15fa03796e789 (diff) |
Write ‘Python functions and classes’ part
This section is complete in English, but is yet to be
translated to Spanish. Mañana.
-rw-r--r-- | python-functions-and-classes.tex | 275 |
1 files changed, 245 insertions, 30 deletions
diff --git a/python-functions-and-classes.tex b/python-functions-and-classes.tex index 483810e..77ee771 100644 --- a/python-functions-and-classes.tex +++ b/python-functions-and-classes.tex @@ -64,6 +64,36 @@ print('El numero mas pequeno es %i' % minimo) \end{lstlisting} \end{frame} +\subsection{\en{Recursion}\es{Recursividad}} + +\en{Functions allow for a new type of control flow: they allow for +\emph{recursion}. Recursion is where a function calls itself and uses the return +value from the call in its calculation. A typical example of this is in +computing mathematical factorials. It's possible to implement this calculation +using a loop, but it's more natural to implement using recursion, as this +mirrors the mathematical definition of factorials.} +\es{TODO} + +\en{As with \texttt{while} loops, ensure your recursion always terminates, or +you will get an infinite recursion, like an infinite loop.} +\es{TODO} + +\begin{frame}[fragile] +\frametitle{\en{Recursion}\es{Recursividad}} +\begin{lstlisting}[language=Python] +def factorial(n): + if n == 0: + return 1 + else: + return n * factorial(n - 1) + +# factorial(n) == n * factorial(n - 1) +# == n * (n-1) * factorial(n - 2) +# ... +# == n * (n-1) * ... * 1 +\end{lstlisting} +\end{frame} + \section{\en{Imports}\es{Importaciónes}} @@ -121,7 +151,12 @@ its variables are separate from those of other instances of the same class.} \en{Why collect functions and variables together? It makes maintaining a large program a lot easier by separating code and data out into different components -which don't interfere with each other.} +which don't interfere with each other. You can think of a class as describing +a single real-world object, such as a vehicle or a table. All the state +(variables) associated with that object is in the class, and all the actions +which can be performed on that object are declared as methods (functions) of the +class. Classes don't \emph{always} correspond to real-world objects, but the +principle stands.} \es{TODO} \en{To define a class in Python, use the \texttt{class} statement, followed by @@ -142,30 +177,38 @@ for the class. It is called when an instance of the class is created, as shown next.} \es{TODO} +\en{Every method in a class must have \texttt{self} as its first +parameter --- this is what makes it a \emph{method}, rather than a +\emph{function}. \texttt{self} is a reference to the object the method is being +called on, and permits access to the object's variables and other methods. To +refer to a variable or method in an instance of a class, use \texttt{self} and +a dot followed by the variable or method name.} +\es{TODO} + \begin{frame}[fragile] \frametitle{\en{Defining classes}\es{Definición de clases}} \begin{lstlisting}[language=Python] class Vehiculo(object): - def __init__(self, matricula, numero_de_ruedas): + def __init__(self, matricula, ruedas): self._matricula = matricula - self._numero_de_ruedas = numero_de_ruedas + self._ruedas = ruedas - # Asumir vehiculos estan gravados por el numero de ruedas + # Asumir vehiculos estan gravados por + # el numero de ruedas. def calcular_impuesto(self): - return 100 * self._numero_de_ruedas + return 100 * self._ruedas def dar_matricula(self): return self._matricula \end{lstlisting} - % TODO: syntax; constructors as special methods; inheritance; properties (definition) - % TODO: class as bundle of functions and variables; instantiating a class; getting/setting a property; calling a method from outside and inside a class instance \end{frame} \en{Instantiating a class is similar to calling a function; you're effectively calling the \texttt{\_\_init\_\_} function, and can pass it parameters as -normal. Once you've instantiated a class, you can call its methods using a -dot --- just like calling \texttt{append()} on a list. All lists are actually -instances of a \texttt{list} class.} +normal. It returns an instance of the class (an object). Once you've +instantiated a class, you can call its methods using a dot --- just like calling +\texttt{append()} on a list. All lists are actually instances of a \texttt{list} +class.} \es{TODO} \begin{frame}[fragile] @@ -175,7 +218,7 @@ mi_coche = Vehiculo('AB99BA', 4) mi_moto = Vehiculo('CB21TA', 2) print(mi_coche.calcular_impuesto()) # da 400 -print(mi_coche.dar_matricula()) # da 'AB99BA' +print(mi_coche.dar_matricula()) # da 'AB99BA' print(mi_moto.calcular_impuesto()) # da 200 \end{lstlisting} \end{frame} @@ -196,32 +239,39 @@ can call the old code in the parent class by using \texttt{super()}.} \begin{frame}[fragile] \frametitle{\en{Defining classes}\es{Definición de clases}} +% Note: I've taken the liberty of using 2-space indents here to get everything +% to fit on the slide. I'm sorry. \begin{lstlisting}[language=Python] class Coche(Vehiculo): - def __init__(self, matricula, peso): - # Todos los coches tienen 4 ruedas - super(Coche, self).__init__(matricula, 4) - self._peso = peso + def __init__(self, matricula, peso): + # Todos los coches tienen 4 ruedas. + super(Coche, self).__init__(matricula, 4) + self._peso = peso - def calcular_presion(self): - return self._peso / 4 + def calcular_presion(self): + return self._peso / 4 class Moto(Vehiculo): - def __init__(self, matricula): - # Todos los motos tienen 2 ruedas - super(Moto, self).__init__(matricula, 2) + def __init__(self, matricula): + # Todos los motos tienen 2 ruedas. + super(Moto, self).__init__(matricula, 2) +\end{lstlisting} +\end{frame} +\begin{frame}[fragile] +\frametitle{\en{Defining classes}\es{Definición de clases}} +\begin{lstlisting}[language=Python] mi_coche = Coche('AB99BA', 1500) mi_moto = Moto('CB21TA') print(mi_coche.calcular_impuesto()) # da 400 -print(mi_coche.dar_matricula()) # da 'AB99BA' +print(mi_coche.dar_matricula()) # da 'AB99BA' print(mi_moto.calcular_impuesto()) # da 200 \end{lstlisting} \end{frame} -\subsection{\en{Private methods}\es{TODO}} +\subsection{\en{Private methods}\es{Métodos privados}} \en{What if you want to define a method in your class but don't want it to be callable from outside the class? For example, a method which performs part of a @@ -231,11 +281,89 @@ then called a \emph{private method}. The same is true for variables, although a single-underscore is commonly used for them.} \es{TODO} +\en{In this example, \texttt{\_\_add\_fuel()} is a private method, and +\texttt{\_remaining\_fuel} and \texttt{\_odometer} are private variables. +\texttt{refuel()} is a \emph{public} method which calls +\texttt{\_\_add\_fuel()}. Why not put the code in \texttt{\_\_add\_fuel()} into +\texttt{refuel()}? Because there may be other methods in the class which cause +fuel to be added to the car, and we want to re-use the code to do so.} +\es{TODO} + \begin{frame}[fragile] -\frametitle{\en{Private methods}\es{TODO}} +\frametitle{\en{Private methods}\es{Métodos privados}} +% Again, I've taken the liberty of using 3-space indents here to make everything +% fit. \begin{lstlisting}[language=Python] class Coche(Vehiculo): - TODO + def __agregar_combustible(self, cantidad): + self._combustible += cantidad + + def repostar(self, cantidad): + self.__agregar_combustible(cantidad) + self._cuentakilometros = 0 +\end{lstlisting} +\end{frame} + + +\subsection{\en{Properties}\es{Propriedades}} + +\en{Often, it is helpful to have a public variable on a class which can be +read and written to by other code. However, it is also often necessary to +execute some code in the class when the variable is written to (for example, to +update other state in the class which depends on that variable, or checking the +new value is acceptable). Python has \emph{properties} for this, which are a +special way of handling variables in a class.} +\es{TODO} + +\begin{frame}[fragile] +\frametitle{\en{Properties}\es{Propriedades}} +\begin{lstlisting}[language=Python] +class Vehiculo(object): + pasajeros = 0 + +mi_coche = Vehiculo() +print(mi_coche.pasajeros) # imprime '0' +mi_coche.pasajeros = 1 +\end{lstlisting} +\end{frame} + +\en{Instead of defining the variable by assigning to it, as in the first +example, assign the result of the special \texttt{property()} function to it +instead. The \texttt{property()} function takes the name of a ``getter'' and a +``setter'' method as its parameters: these are called when the property is +read or written, respectively.} +\es{TODO} + +\begin{frame}[fragile] +\frametitle{\en{Properties}\es{Propriedades}} +\begin{lstlisting}[language=Python] +class Vehiculo(object): + def __init__(self, escanos): + self._pasajeros = 0 + self._escanos = escanos + + def get_pasajeros(self): + return self._pasajeros + + def set_pasajeros(self, valor): + if valor <= self._escanos: + self._pasajeros = valor + else: + print('Demasiados pasajeros!') + + # Propriedad + pasajeros = property(get_pasajeros, + set_pasajeros) +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile] +\frametitle{\en{Properties}\es{Propriedades}} +\begin{lstlisting}[language=Python] +mi_coche = Vehiculo(5) # 5 escanos +mi_coche.pasajeros = 3 +print(mi_coche.pasajeros) # imprime '3' +mi_coche.pasajeros = 6 # imprime 'Demasiados!' \end{lstlisting} \end{frame} @@ -253,23 +381,110 @@ method being documented.} \frametitle{\en{Documentation}\es{Documentación}} \begin{lstlisting}[language=Python] class Vehiculo(object): - """TODO""" - def my_method(self, foo): - """TODO""" - return 15 + """Un vehiculo generico. + + Esto puede repostar, guardar la distancia + recorrida por el vehiculo, y contar el + numero de pasajes. + """ + def repostar(self, cantidad): + """Anadir cantidad litros de + combustible para el vehiculo.""" + self._combustible += cantidad \end{lstlisting} \end{frame} \en{You can access documentation from the Python interpreter by accessing the -\texttt{\_\_doc\_\_} member variable of the class or method. +\texttt{\_\_doc\_\_} member variable of the class or method.} +\es{TODO} \begin{frame}[fragile] \frametitle{\en{Documentation}\es{Documentación}} \begin{lstlisting}[language=Python] print(Vehiculo.__doc__) +print(Vehiculo.repostar.__doc__) print(range.__doc__) \end{lstlisting} \end{frame} -% TODO: git, licensing, basic GTK+ usage, code formatting/peps +\section{\en{Code formatting}\es{Formato de código}} + +\en{As with documentation, consistent and clear code formatting is important in +making code readable. Python has two tools available to help checking programs +for formatting errors and other errors: \texttt{pylint} and \texttt{pep8}.} +\es{TODO} + +\en{They should be run after making large additions to the code, or before +releasing a program to others.} +\es{TODO} + +\begin{frame}{\en{Code formatting}\es{Formato de código}} +\en{In a terminal:}\es{En un terminal:} +\begin{itemize} + \item{\texttt{pylint \en{my-file.py}\es{mi-archivo.py}}} + \item{\texttt{pep8 \en{my-file.py}\es{mi-archivo.py}}} +\end{itemize} +\end{frame} + + +\section{\en{GUIs with GTK+}\es{TODO}} + +\en{Creating user interfaces (GUIs) will be covered in more detail in +\autoref{part:writing-sugar-activities}, but it's useful to cover a simple +example now as a demonstration of the use of classes.} +\es{TODO} + +\en{In the GTK+ UI toolkit, every on-screen UI element (or \emph{widget}) is an +object --- an instance of a class. For example, there's a \texttt{Button} class +which is instantiated for every button in a program. In this example, the +\texttt{Window} and \texttt{Button} classes are instantiated to give a window +containing a button. The example is cut down to its bare minimum, and is not a +useful program.} +\es{TODO} + +\begin{frame}[fragile] +\frametitle{\en{GUI example}\es{Ejemplo de GUI}} +\begin{lstlisting}[language=Python] +from gi.repository import Gtk + +ventana = Gtk.Window('Hola mundo') +boton = Gtk.Button('Un boton') +ventana.add(boton) +ventana.show_all() + +Gtk.main() +\end{lstlisting} +\end{frame} + + +\section{\en{Licencing}\es{Licencias}} + +\en{An important part of the Sugar project is that it is free software --- in +the sense that anyone has the freedom to read and modify the source code. To +upload an activity to \url{http://activities.sugarlabs.org/} it must use a +free software licence. This is important, as it allows students to view and +learn from the code running their activities, and potentially modify it to +improve the activities.} +\es{TODO} + +\en{There are several major free software licences, and you must choose one +which matches your ideology. The most relevant three licences are: GPL, MIT and +BSD. The Sugar project itself uses GPL.} +\es{TODO} + +\begin{frame}{\en{Licencing}\es{Licencias}} + +\begin{block}{} +\url{http://gnu.org/licenses/license-recommendations.html} +\end{block} + +\begin{block}{} +\begin{description} + \item[GPL]{\url{http://\en{en}\es{es}.wikipedia.org/wiki/GNU_General_Public_License}} + \item[MIT]{\url{http://\en{en}\es{es}.wikipedia.org/wiki/MIT_License}} + \item[BSD]{\url{\en{http://en.wikipedia.org/wiki/BSD_licenses} + \es{http://es.wikipedia.org/wiki/Licencia_BSD}}} +\end{description} +\end{block} +\end{frame} |