{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introducción a la programación en Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Versión original en inglés de J.R. Johansson (robert@riken.jp) http://jrjohansson.github.io/.\n", "\n", "Traducido/Adaptado por [G.F. Rubilar](http://google.com/+GuillermoRubilar).\n", "\n", "La última versión de estos [notebooks de IPython](http://ipython.org/notebook.html) está disponible en [http://github.com/gfrubi/clases-python-cientifico](http://github.com/gfrubi/clases-python-cientifico).\n", "\n", "La última versión del original (en inglés) de estos [notebooks de IPython](http://ipython.org/notebook.html) está disponible en [http://github.com/jrjohansson/scientific-python-lectures](http://github.com/jrjohansson/scientific-python-lectures).\n", "\n", "Los otros notebooks de esta serie están listados en [http://jrjohansson.github.com](http://jrjohansson.github.com)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Archivos de programa en Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* El código Python es usualmente almacenado en archivos de texto con entensión \"`.py`\":\n", "\n", " miprograma.py\n", "\n", "* Se asume que cada línea de un archivo de programa en Python es una sentencia Python, o parte de una sentencia. \n", "\n", " * La única excepción son las líneas de comentarios, que comienzan con el caracter `#` (opcionalmente precedida por un número arbitrario de caracteres de espacio en blanco, es decir, tabs y espacios. Las líneas de comentarios son usualmente ignoradas por el intérprete Python.\n", "\n", "\n", "* Para ejecutar nuestro programa Python desde la línea de comando usamos:\n", "\n", " $ python miprograma.py\n", "\n", "* En sistemas UNIX es común definir la ruta al intérprete en la primera línea del programa (note que ésta es una línea de comentarios en lo que respecta al intérprete Python):\n", "\n", " #!/usr/bin/env python\n", "\n", " Si hacemos esto, y adicionalmente configuramos el archivo para que sea ejecutable, podemos correr el programa usando:\n", "\n", " $ miprograma.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejemplo" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "scripts/hola-mundo-en-sueco.py scripts/hola-mundo.py\r\n" ] } ], "source": [ "ls scripts/hola-mundo*.py" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#!/usr/bin/env python\r\n", "\r\n", "print(\"Hola mundo!\")\r\n" ] } ], "source": [ "cat scripts/hola-mundo.py" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hola mundo!\r\n" ] } ], "source": [ "!python scripts/hola-mundo.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Codificación de caracteres" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La codificación estándar de caracteres es la ASCII, pero podemos usar cualquier otra codificación, por ejemplo UTF-8. Para especificar que usamos UTF-8 incluimos la línea especial\n", "\n", " # -*- coding: UTF-8 -*-\n", "\n", "al comienzo del archivo." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "#!/usr/bin/env python\r\n", "# -*- coding: UTF-8 -*-\r\n", "\r\n", "print(\"Hej världen!\")\r\n" ] } ], "source": [ "cat scripts/hola-mundo-en-sueco.py" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hej världen!\r\n" ] } ], "source": [ "!python scripts/hola-mundo-en-sueco.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aparte de estas dos líneas *opcionales* al comienzo de un archivo Python, no se requiere de otro código adicional para inicializar un programa. Por otro lado, en la versión 3 de Python ya no es necesario agregar código extra alguno." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Notebooks de IPython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Este archivo - un notebook IPython - no sigue el patrón estándar de código Python en un archivo de texto. En su lugar, un notebook IPython es almacenado como un archivo en el formato [JSON](http://es.wikipedia.org/wiki/JSON). La ventaja es que podemos mezclar texto formateado, código Python, y código de salida. Esto requiere estar ejecutando un servidor de notebook IPython, y por eso este tipo de archivo no es un programa Python independiente como se describió antes. Aparte de eso, no hay diferencia entre el código Python en un archivo de programa o en un notebook IPython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Variables y tipos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nombres de símbolos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Los nombres de las variables en Python pueden contener los caracteres `a-z`, `A-Z`, `0-9` y algunos caracteres especiales como `_`. Los nombres de variables normales deben comenzar con una letra. \n", "\n", "Por convención, los nombres de las variables comienzan con letra minúscula, mientras que los nombres de las clases comienzan con una letra mayúscula. \n", "\n", "Además, existen algunos palabras claves Python que no pueden ser usados como nombres de variables. Éstas son:\n", "\n", " and, as, assert, break, class, continue, def, del, elif, else, except, \n", " exec, finally, for, from, global, if, import, in, is, lambda, not, or,\n", " pass, print, raise, return, try, while, with, yield\n", "\n", "Nota: Atención con la palabra `lambda`, que podría fácilmente ser un nombre de variable natural en un programa científico. Sin embargo, como es una palabra clave, no puede ser usado como nombre de una variable." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Asignaciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El operador para asignar valores en Python es el signo igual (`=`). Python es un lenguage de _escritura dinámica_, de modo que no necesitamos especificar el tipo de una variable cuando la creamos.\n", "\n", "Al asignar un valor a una variable nueva se crea esa variable:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# asignaciones de variables\n", "x = 1.0\n", "mi_variable = 12.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aunque no se especifique explícitamente, cada variable sí tiene un tipo asociada a ella. El tipo es extraido del valor que le fue asignado." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "float" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si asignamos un nuevo valor a una variable, su tipo puede cambiar." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x = 1" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si tratamos de unsar una variable que no ha sido definida obtenemo un mensaje de error (`NameError`):" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "ename": "NameError", "evalue": "name 'y' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mNameError\u001b[0m: name 'y' is not defined" ] } ], "source": [ "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tipos Fundamentales" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "int" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# enteros\n", "x = 1\n", "type(x)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "float" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# flotantes\n", "x = 1.0\n", "type(x)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "bool" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# booleanos\n", "b1 = True\n", "b2 = False\n", "\n", "type(b1)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "complex" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# números complejos: note que se usa `j` para especificar la parte imaginaria\n", "x = 1.0 - 1.0j\n", "type(x)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1-1j)\n" ] } ], "source": [ "print(x)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1.0, -1.0)\n" ] } ], "source": [ "print(x.real, x.imag)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Funciones de relacionadas con Tipos\n", "\n", "El módulo `types` contiene definiciones de nombres de tipo que pueden ser usadas para testear si las variables son de un cierto tipo:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['BooleanType', 'BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', 'ComplexType', 'DictProxyType', 'DictType', 'DictionaryType', 'EllipsisType', 'FileType', 'FloatType', 'FrameType', 'FunctionType', 'GeneratorType', 'GetSetDescriptorType', 'InstanceType', 'IntType', 'LambdaType', 'ListType', 'LongType', 'MemberDescriptorType', 'MethodType', 'ModuleType', 'NoneType', 'NotImplementedType', 'ObjectType', 'SliceType', 'StringType', 'StringTypes', 'TracebackType', 'TupleType', 'TypeType', 'UnboundMethodType', 'UnicodeType', 'XRangeType', '__builtins__', '__doc__', '__file__', '__name__', '__package__']\n" ] } ], "source": [ "import types\n", "\n", "# imprime todos los tipos definidos en el módulo `types`\n", "print(dir(types))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 1.0\n", "\n", "# verifica si la variable x es flotante\n", "type(x) is float" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# verifica si la variable x es un entero\n", "type(x) is int" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos también usar el método `isinstance` para testear tipos de variables:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(x, float)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Conversión de Tipo" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1.5, )\n" ] } ], "source": [ "x = 1.5\n", "\n", "print(x, type(x))" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, )\n" ] } ], "source": [ "x = int(x)\n", "\n", "print(x, type(x))" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((1+0j), )\n" ] } ], "source": [ "z = complex(x)\n", "\n", "print(z, type(z))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "ename": "TypeError", "evalue": "can't convert complex to float", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mz\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: can't convert complex to float" ] } ], "source": [ "x = float(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Un número complejo no puede ser convertido a un número flotante o a un entero. Necesitamos usar `z.real`, o bien `z.imag`, para extraer la parte que deseamos del número complejo z:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1.0, ' -> ', True, )\n", "(0.0, ' -> ', False, )\n" ] } ], "source": [ "y = bool(z.real)\n", "\n", "print(z.real, \" -> \", y, type(y))\n", "\n", "y = bool(z.imag)\n", "\n", "print(z.imag, \" -> \", y, type(y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Operadores y comparaciones\n", "\n", "La mayoría de los operadores y las comparaciones en Python funcionan como one esperaría:\n", "\n", "* Operadores aritméticos `+`, `-`, `*`, `/`, `//` (división entera), '**' potencia\n" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(3, -1, 2, 0)" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 + 2, 1 - 2, 1 * 2, 1 / 2" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(3.0, -1.0, 2.0, 0.5)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1.0 + 2.0, 1.0 - 2.0, 1.0 * 2.0, 1.0 / 2.0" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# División entera de dos númenos flotantes\n", "3.0 // 2.0" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Atención! El operador de potencia en Python no es ^, sino **\n", "2 ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Los operadores booleanos se escriben como palabras: `and`, `not`, `or`. " ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "True and False" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "not False" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "True or False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Operadores de comparación `>`, `<`, `>=` (mayor o igual), `<=` (menor o igual), `==` igualdad, `es` identico." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(True, False)" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 > 1, 2 < 1" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(False, False)" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 > 2, 2 < 2" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(True, True)" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 >= 2, 2 <= 2" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# igualdad\n", "[1,2] == [1,2]" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ¿objetos identicos?\n", "l1 = l2 = [1,2]\n", "\n", "l1 is l2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tipos compuestos: Cadenas, listas y diccionarios\n", "\n", "### Cadenas\n", "\n", "Las cadenas son el tipo de variables que es usado para almacenar mensajes de texto. " ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = \"Hola mundo\"\n", "type(s)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# longitud de la cadena: el número de caracteres que contiene\n", "len(s)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hola universo\n" ] } ], "source": [ "# reemplaza una subcadena de una cadena por cadena\n", "s2 = s.replace(\"mundo\", \"universo\")\n", "print(s2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos aislar un carácter en una cadena usando `[]`:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'H'" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Atención usuarios de MATLAB:** el indexado comienza en 0!\n", "\n", "Podemos extraer una parte de una cadena usando la sintaxis `[desde:hasta]`, que extrae caracteres entre los índices `desde` y `hasta`:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hola '" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[0:5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si omitimos `desde` o bien `hasta` de `[desde:hasta]`, por defecto se entiende que se refiere al comienzo y/o al fin de la cadena, respectivamente:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hola '" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[:5]" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'undo'" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[6:]" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hola mundo'" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos también definir el tamaño del paso usando la sintaxis `[desde:hasta:paso]` (el valor por defecto de `paso` es 1, como ya vismo):" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hola mundo'" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[::1]" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hl ud'" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s[::2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esta técnica es llamada *slicing* (\"rebanado\"). Puede leer más sobre la sintaxis aquí [http://pyspanishdoc.sourceforge.net/lib/built-in-funcs.html](http://pyspanishdoc.sourceforge.net/lib/built-in-funcs.html) y aquí (en inglés) [http://docs.python.org/release/2.7.3/library/functions.html?highlight=slice#slice](http://docs.python.org/release/2.7.3/library/functions.html?highlight=slice#slice)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python tiene un rico conjunto de funciones para procesar texto. Ver por ejemplo [http://docs.python.org/2/library/string.html](http://docs.python.org/2/library/string.html) (en inglés) para más información." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ejemplos de formateo de cadenas" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('uno', 'dos', 'tres')\n" ] } ], "source": [ "print(\"uno\", \"dos\", \"tres\") # El comando print puede desplegar varias cadenas" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('uno', 1.0, False, -1j)\n" ] } ], "source": [ "print(\"uno\", 1.0, False, -1j) # El comendo print convierte todos los argumentos a cadenas" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "unodostres\n" ] } ], "source": [ "print(\"uno\" + \"dos\" + \"tres\") # cadenas \"sumadas\" con + son contatenadas sin espacio entre ellas" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "valor = 1.000000\n" ] } ], "source": [ "print(\"valor = %f\" % 1.0) # podemos usar formateo de cadenas en el estilo del lenguaje C" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "valor1 = 3.14. valor2 = 1\n" ] } ], "source": [ "# este formateo crea una cadena\n", "s2 = \"valor1 = %.2f. valor2 = %d\" % (3.1415, 1.5)\n", "\n", "print(s2)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "valor1 = 3.1415, valor2 = 1.5\n" ] } ], "source": [ "# forma alternativa, más intuitiva para formatear una cadena\n", "s3 = 'valor1 = {0}, valor2 = {1}'.format(3.1415, 1.5)\n", "\n", "print(s3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Listas\n", "\n", "Listas son muy similares a las cadenas, excepto que cada elemento puede ser de un tipo diferente.\n", "\n", "La sintaxis para crear listas en Python es `[..., ..., ...]`:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[1, 2, 3, 4]\n" ] } ], "source": [ "l = [1,2,3,4]\n", "\n", "print(type(l))\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos usar las mismas técnicas de \"rebanado\" que usamos en el caso de cadenas para manipular listas:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4]\n", "[2, 3]\n", "[1, 3]\n" ] } ], "source": [ "print(l)\n", "\n", "print(l[1:3])\n", "\n", "print(l[::2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Atención usuarios de MATLAB:** el indexado comienza en 0!" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Los elementos en una lista no requieren ser del mismo tipo:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 'a', 1.0, (1-1j)]\n" ] } ], "source": [ "l = [1, 'a', 1.0, 1-1j]\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las listas en Python pueden ser inhomogéneas y arbitrariamente anidadas:" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[1, [2, [3, [4, [5]]]]]" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lista_anidada = [1, [2, [3, [4, [5]]]]]\n", "\n", "lista_anidada" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las listas juegan un rol muy importante en Python y son, por ejemplo, usadas en bucles y otras estructuras de control de flujo (discutidas más abajo). Existan muchas funciones convenientes para generar listas de varios tipos, por ejemplo la función `range`:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[10, 12, 14, 16, 18, 20, 22, 24, 26, 28]" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "desde = 10\n", "hasta = 30\n", "paso = 2\n", "\n", "range(desde, hasta, paso)" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[10, 12, 14, 16, 18, 20, 22, 24, 26, 28]" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# en Python 3 range genera un interador, que puede ser convertido a una lista usando 'list(...)'. Esto no tiene efecto en Python 2\n", "list(range(desde, hasta, paso))" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(-10, 10))" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Hola mundo'" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['H', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o']" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# convierte una cadena a una lista, por conversión de tipo:\n", "\n", "s2 = list(s)\n", "\n", "s2" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[' ', 'H', 'a', 'd', 'l', 'm', 'n', 'o', 'o', 'u']\n" ] } ], "source": [ "# ordenando listas\n", "s2.sort()\n", "\n", "print(s2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Agregando, insertando, modificando, y removiendo elementos de listas" ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 'd', 'd']\n" ] } ], "source": [ "# crea una nueva lista vacía\n", "l = []\n", "\n", "# agrega un elemento usando `append`\n", "l.append(\"A\")\n", "l.append(\"d\")\n", "l.append(\"d\")\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos modificar listas asignando nuevos valores a los elementos de la lista. En lenguaje técnico se dice que la lista es *mutable*." ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 'p', 'p']\n" ] } ], "source": [ "l[1] = \"p\"\n", "l[2] = \"p\"\n", "\n", "print(l)" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 'd', 'd']\n" ] } ], "source": [ "l[1:3] = [\"d\", \"d\"]\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Insertar un elemento en una posición específica `insert`" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['i', 'n', 's', 'e', 'r', 't', 'A', 'd', 'd']\n" ] } ], "source": [ "l.insert(0, \"i\")\n", "l.insert(1, \"n\")\n", "l.insert(2, \"s\")\n", "l.insert(3, \"e\")\n", "l.insert(4, \"r\")\n", "l.insert(5, \"t\")\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eliminar el primer elemento con un valor específico usando 'remove'" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['i', 'n', 's', 'e', 'r', 't', 'd', 'd']\n" ] } ], "source": [ "l.remove(\"A\")\n", "\n", "print(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eliminar un elemento en una posición específica usando `del`:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Puede introducir `help(list)` para más detalles, o leer la documentación en la red" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tuplas\n", "\n", "Tuplas son similares a las listas, excepto que ellas no pueden ser modificadas una vez creadas, es decir, son *inmutables*. \n", "\n", "En Python, las tuplas son creadas usando la sintaxis `(..., ..., ...)`, o incluso `..., ...`:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((10, 20), )\n" ] } ], "source": [ "punto = (10, 20)\n", "\n", "print(punto, type(punto))" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((10, 20), )\n" ] } ], "source": [ "punto = 10, 20\n", "\n", "print(punto, type(punto))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos separar una tupla asignandola a una lista de variables separadas por coma:" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('x =', 10)\n", "('y =', 20)\n" ] } ], "source": [ "x, y = punto\n", "\n", "print(\"x =\", x)\n", "print(\"y =\", y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si intentamos asignar un nuevo valor a un elemento de una tupla obtenemos un error:" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "collapsed": false }, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mpunto\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m20\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "source": [ "punto[0] = 20" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dictionarios\n", "\n", "Dictionarios son también como listas, excepto que cada elemento es un par clave-valor. La sintaxsis de los diccionarios es `{clave1 : valor1, ...}`:" ] }, { "cell_type": "code", "execution_count": 84, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "{'parametro1': 1.0, 'parametro3': 3.0, 'parametro2': 2.0}\n" ] } ], "source": [ "parametros = {\"parametro1\" : 1.0,\n", " \"parametro2\" : 2.0,\n", " \"parametro3\" : 3.0,}\n", "\n", "print(type(parametros))\n", "print(parametros)" ] }, { "cell_type": "code", "execution_count": 85, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "parametro1 = 1.0\n", "parametro2 = 2.0\n", "parametro3 = 3.0\n" ] } ], "source": [ "print(\"parametro1 = \" + str(parametros[\"parametro1\"]))\n", "print(\"parametro2 = \" + str(parametros[\"parametro2\"]))\n", "print(\"parametro3 = \" + str(parametros[\"parametro3\"]))" ] }, { "cell_type": "code", "execution_count": 86, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "parametro1 = A\n", "parametro2 = B\n", "parametro3 = 3.0\n", "parametro4 = D\n" ] } ], "source": [ "parametros[\"parametro1\"] = \"A\"\n", "parametros[\"parametro2\"] = \"B\"\n", "\n", "# agrega una nueva entrada\n", "parametros[\"parametro4\"] = \"D\"\n", "\n", "print(\"parametro1 = \" + str(parametros[\"parametro1\"]))\n", "print(\"parametro2 = \" + str(parametros[\"parametro2\"]))\n", "print(\"parametro3 = \" + str(parametros[\"parametro3\"]))\n", "print(\"parametro4 = \" + str(parametros[\"parametro4\"]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Control de flujo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sentencias condicionales: if, elif, else\n", "\n", "La sintaxis Python para la ejecución condicional de código usa las palabras clave `if`, `elif` (else if), `else`:" ] }, { "cell_type": "code", "execution_count": 87, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "afirmacion1 y afirmacion2 son falsas\n" ] } ], "source": [ "afirmacion1 = False\n", "afirmacion2 = False\n", "\n", "if afirmacion1:\n", " print(\"afirmacion1 es verdadera\")\n", " \n", "elif afirmacion2:\n", " print(\"afirmacion2 es verdadera\")\n", " \n", "else:\n", " print(\"afirmacion1 y afirmacion2 son falsas\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aquí encontramos por primera un aspecto pecular e inusual del lenguaje Python: Los bloques del programa son definidos por su nivel de indentación (la cantidad de espacio antes de cada linea). \n", "\n", "Compare con el código equivalente en C:\n", "\n", " if (afirmacion1)\n", " {\n", " printf(\"afirmacion1 es verdadera\\n\");\n", " }\n", " else if (afirmacion2)\n", " {\n", " printf(\"afirmacion1 es verdadera\\n\");\n", " }\n", " else\n", " {\n", " printf(\"afirmacion1 y afirmacion2 son falsas\\n\");\n", " }\n", "\n", "En C los bloques son definidos por los paréntesis llaves `{` y `}`. El nivel de indentación (espacio en blanco antes del código) no importa (es completamente opcional). \n", "\n", "En Python, la extensión de un bloque de código es definido por el nivel de indentación (usualmente un tab o cuatro espacios en blanco). Esto significa que debemos ser cuidados@s de indentar nuestro código correctamente, de lo contrario tendremos errores de sintaxis. \n", "\n", "**Ejemplos:**" ] }, { "cell_type": "code", "execution_count": 88, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tanto afirmacion1 como afirmacion2 son verdaderas\n" ] } ], "source": [ "afirmacion1 = afirmacion2 = True\n", "\n", "if afirmacion1:\n", " if afirmacion2:\n", " print(\"tanto afirmacion1 como afirmacion2 son verdaderas\")" ] }, { "cell_type": "code", "execution_count": 89, "metadata": { "collapsed": false }, "outputs": [ { "ename": "IndentationError", "evalue": "expected an indented block (, line 4)", "output_type": "error", "traceback": [ "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m4\u001b[0m\n\u001b[1;33m print(\"tanto afirmacion1 como afirmacion2 son verdaderas\") # esta línea está mal indentada\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mIndentationError\u001b[0m\u001b[1;31m:\u001b[0m expected an indented block\n" ] } ], "source": [ "# Mala indentación!\n", "if afirmacion1:\n", " if afirmacion2:\n", " print(\"tanto afirmacion1 como afirmacion2 son verdaderas\") # esta línea está mal indentada" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "afirmacion1 = False \n", "\n", "if afirmacion1:\n", " print(\"afirmacion1 es verdadera\")\n", " \n", " print(\"aun estamos dentro del bloque if\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "if afirmacion1:\n", " print(\"afirmacion1 es verdadera\")\n", " \n", "print(\"ahora estamos fuera del bloque\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ciclos\n", "\n", "En Python, los ciclos (loops) puede ser programados de varias maneras diferentes. La forma más común es usando un cicle `for`, que se usa junto con objetos iterables, como por ejemplos las listas. La sintaxis básica es:\n", "\n", "\n", "**Ciclos `for`**:" ] }, { "cell_type": "code", "execution_count": 90, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n" ] } ], "source": [ "for x in [1,2,3]:\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El ciclo `for` itera sobre los elementos de la lista suministrada y ejecuta el bloque suministrado una vez para cada elemento. Cualquier tipo de lista puede ser usada para un ciclo `for`. Por ejemplo:" ] }, { "cell_type": "code", "execution_count": 91, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n" ] } ], "source": [ "for x in range(4): # por defecto range comienza con 0\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nota: `range(4)` no incluye el 4 !" ] }, { "cell_type": "code", "execution_count": 92, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-3\n", "-2\n", "-1\n", "0\n", "1\n", "2\n" ] } ], "source": [ "for x in range(-3,3):\n", " print(x)" ] }, { "cell_type": "code", "execution_count": 93, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "computación\n", "científica\n", "con\n", "Python\n" ] } ], "source": [ "for palabra in [\"computación\", \"científica\", \"con\", \"Python\"]:\n", " print(palabra)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para iterar sobre pares clave-valor en un diccionario:" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "parametro1 = A\n", "parametro3 = 3.0\n", "parametro2 = B\n", "parametro4 = D\n" ] } ], "source": [ "for clave, valor in parametros.items():\n", " print(clave + \" = \" + str(valor))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Algunas veces es útil tener acceso a los índices de los valores mientras se itera sobre una lista. Podemos usar la función `enumerate` para esto:" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0, -3)\n", "(1, -2)\n", "(2, -1)\n", "(3, 0)\n", "(4, 1)\n", "(5, 2)\n" ] } ], "source": [ "for idx, x in enumerate(range(-3,3)):\n", " print(idx, x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "** Listas: Creando listas usando ciclos `for`**:\n", "\n", "Una forma conveniente y compacta de inicializar listas:" ] }, { "cell_type": "code", "execution_count": 96, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 4, 9, 16]\n" ] } ], "source": [ "l1 = [x**2 for x in range(0,5)]\n", "\n", "print(l1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Ciclos `while`**:" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "listo\n" ] } ], "source": [ "i = 0\n", "\n", "while i < 5:\n", " print(i) \n", " i = i + 1\n", " \n", "print(\"listo\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que el comando`print(\"listo\")` no es parte del cuerpo del ciclo `while`, debido a su indentación." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Funciones\n", "\n", "En Python una función es definida usando la palabra clave `def`, seguida de un nombre para la función, una variable entre paréntesis `()`, y el símbolo de dos puntos `:`. El siguiente código, con un nivel adicional de indentación, is el cuerpo de la función." ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def func0(): \n", " print(\"test\")" ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n" ] } ], "source": [ "func0()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En forma opcional, pero muy recomendada, podemos definir un \"docstring\", que es una descripción del propósito y comportamiento de la función. El docstring debería ser incluido directamente después de la definición de la función, antes del código en el cuerpo de la función." ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def func1(s):\n", " \"\"\"\n", " Imprime la cadena 's' y dice cuántos caracteres tiene\n", " \"\"\"\n", " \n", " print(s + \" tiene \" + str(len(s)) + \" caracteres\")" ] }, { "cell_type": "code", "execution_count": 101, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function func1 in module __main__:\n", "\n", "func1(s)\n", " Imprime la cadena 's' y dice cuántos caracteres tiene\n", "\n" ] } ], "source": [ "help(func1)" ] }, { "cell_type": "code", "execution_count": 102, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test tiene 4 caracteres\n" ] } ], "source": [ "func1(\"test\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Funciones que retornan un valor usan la palabra clave `return`:" ] }, { "cell_type": "code", "execution_count": 103, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def cuadrado(x):\n", " \"\"\"\n", " Calcula el cuadrado de x.\n", " \"\"\"\n", " return x**2" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cuadrado(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos retornar múltiples valores desde una función usando las tuplas (ver más arriba):" ] }, { "cell_type": "code", "execution_count": 105, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def potencias(x):\n", "dir \"\"\"\n", " Calcula algunas potencias de x.\n", " \"\"\"\n", " return x**2, x**3, x**4" ] }, { "cell_type": "code", "execution_count": 106, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(9, 27, 81)" ] }, "execution_count": 106, "metadata": {}, "output_type": "execute_result" } ], "source": [ "potencias(3)" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "27\n" ] } ], "source": [ "x2, x3, x4 = potencias(3)\n", "\n", "print(x3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Argumentos por defecto y argumentos de palabra clave\n", "\n", "En la definición de una función, podemos asignar valores por defecto a los argumentos de la función:" ] }, { "cell_type": "code", "execution_count": 108, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def mifunc(x, p=2, debug=False):\n", " if debug:\n", " print(\"evaluando mifunc para x = \" + str(x) + \" usando el exponente p = \" + str(p))\n", " return x**p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si no suministramos un valor para el argumento `debug` al llamar a la función `mifunc` se considera el valor definido por defecto:" ] }, { "cell_type": "code", "execution_count": 109, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "25" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mifunc(5)" ] }, { "cell_type": "code", "execution_count": 110, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "evaluando mifunc para x = 5 usando el exponente p = 2\n" ] }, { "data": { "text/plain": [ "25" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mifunc(5, debug=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si listamos explícitamente el nombre de los argumentos al llamar una función, ellos no necesitan estar en el mismo orden usando en la definición de la función. Esto es llamado argumentos *de palabra clave* (keyword), y son a menudo muy útiles en funciones que requieren muchos argumentos opcionales." ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "evaluando mifunc para x = 7 usando el exponente p = 3\n" ] }, { "data": { "text/plain": [ "343" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mifunc(p=3, debug=True, x=7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Funciones sin nombre (funciones lambda)\n", "\n", "En Python podemos también crear funciones sin nombre, usando la palabra clave `lambda`:" ] }, { "cell_type": "code", "execution_count": 112, "metadata": { "collapsed": false }, "outputs": [], "source": [ "f1 = lambda x: x**2\n", " \n", "# es equivalente a \n", "\n", "def f2(x):\n", " return x**2" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(4, 4)" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1(2), f2(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esta técnica es útil, por ejemplo, cuando queremos pasar una función simple como argumento de otra función, como en este caso:" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[9, 4, 1, 0, 1, 4, 9]" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# map es una función predefinida en Python\n", "map(lambda x: x**2, range(-3,4))" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[9, 4, 1, 0, 1, 4, 9]" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# in Python 3 podemos usar `list(...)` para convertir la iteración a una lista explícita\n", "list(map(lambda x: x**2, range(-3,4)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Clases\n", "\n", "Las clases son una característica clave de la programación orientada al objeto. Una clase es una estructura para representar un objeto y las operaciones que pueden ser realizadas sobre el objeto. \n", "\n", "En Python una clase puede contener *atributos* (variables) y *métodos* (funciones).\n", "\n", "En Python una clase es definida casi como una función, pero usando la palabra clave `class`, y la definición de la clase usualmente contiene algunas definiciones de métodos (una función en una clase).\n", "\n", "* Cada método de una clase debería tener un argumento `self` como su primer argumento. Este objeto es una autoreferencia.\n", "\n", "* Algunos nombres de métodos de clases tienen un significado especial, por ejemplo:\n", "\n", " * `__init__`: El nombre del método que es invocado cuando el objeto es creado por primera vez.\n", " * `__str__` : Un método que es invocado cuando se necesita una simple representación de cadena de la clase, como por ejemplo cuando se imprime.\n", " * Existen muchas más, ver http://docs.python.org/2/reference/datamodel.html#special-method-names" ] }, { "cell_type": "code", "execution_count": 116, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Punto:\n", " \"\"\"\n", " Clase simple para representar un punto en un sistema de coordenadas cartesiano.\n", " \"\"\"\n", " \n", " def __init__(self, x, y):\n", " \"\"\"\n", " Crea un nuevo punto en x, y.\n", " \"\"\"\n", " self.x = x\n", " self.y = y\n", " \n", " def traslada(self, dx, dy):\n", " \"\"\"\n", " Traslada el punto en dx y dy en las direcciones x e y respectivamente.\n", " \"\"\"\n", " self.x += dx\n", " self.y += dy\n", " \n", " def __str__(self):\n", " return(\"Punto en [%f, %f]\" % (self.x, self.y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para crear una nuva instancia de una clase:" ] }, { "cell_type": "code", "execution_count": 117, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Punto en [0.000000, 0.000000]\n" ] } ], "source": [ "p1 = Punto(0, 0) # eso invoca el método __init__ en la cláse Punto\n", "\n", "print(p1) # esto invoca el método __str__ " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para invocar un método en la instancia de clase `p`:" ] }, { "cell_type": "code", "execution_count": 118, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Punto en [0.250000, 1.500000]\n", "Punto en [1.000000, 1.000000]\n" ] } ], "source": [ "p2 = Punto(1, 1)\n", "\n", "p1.traslada(0.25, 1.5)\n", "\n", "print(p1)\n", "print(p2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que llamar a métodos de clases puede modificar el estado de esa instancia de clase particular, pero no afecta otras instancias de la clase o alguna otra variable global.\n", "\n", "Esto es una de las cosas buenas de un diseño orientado al objeto: código como las funciones y variables relacionadas son agrupadas en entidades separadas e independientes. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Módulos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La mayoría de la funcionalidad en Python es provista por *módulos*. La Librería Estándar de Python es una gran colección de módulos que proveen implementaciones *multiplataforma* de recursos tales como el acceso al sistema operativo, entrada/salido de archivos (file I/O), manejo de cadenas, comunicación en redes, y mucho más.\n", "\n", "Para usar un módulo en un programa Python éste debe primero ser **importado**. Un módulo puede ser importado usando el comando `import`. Por ejemplo, para importar el módulo `math`, que contiene muchas funciones matemáticas estándar, podemos usar:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esto incluye el módulo completo y lo deja disponible para su uso en el programa. Por ejemplo, podemos escribir:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "import math\n", "\n", "x = math.cos(2 * math.pi)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternativamente, podemos elegir importar todos los símbolos (funciones y variables) en un módulo al espacio de nombres (namespace) actual (de modo que no necesitemos usar el prefijo \"`math.`\" cada vez que usemos algo del módulo `math`:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "from math import *\n", "\n", "x = cos(2 * pi)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esta forma de proceder puede ser muy conveniente, pero en programas largos que incluyen muchos módulos es a menudo una buena idea mantener los símbolos de cada módulo en sus propios espacios de nombres, usando `import math`. Esto elimina potenciales confusiones con eventuales colisiones de nombres.\n", "\n", "Como una tercera alternativa, podemos importar sólo algunos símbolos seleccionados desde un módulo listando explícitamente aquellos símbolos que deseamos importar, en lugar de usar el carácter comodín `*`:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "from math import cos, pi\n", "\n", "x = cos(2 * pi)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mirando qué contiene un módulo, y su documentación" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Luego que se ha cargado un módulo, podemos listar los símbolos que éste provee usando la función `dir`:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['__doc__',\n", " '__name__',\n", " '__package__',\n", " 'acos',\n", " 'acosh',\n", " 'asin',\n", " 'asinh',\n", " 'atan',\n", " 'atan2',\n", " 'atanh',\n", " 'ceil',\n", " 'copysign',\n", " 'cos',\n", " 'cosh',\n", " 'degrees',\n", " 'e',\n", " 'erf',\n", " 'erfc',\n", " 'exp',\n", " 'expm1',\n", " 'fabs',\n", " 'factorial',\n", " 'floor',\n", " 'fmod',\n", " 'frexp',\n", " 'fsum',\n", " 'gamma',\n", " 'hypot',\n", " 'isinf',\n", " 'isnan',\n", " 'ldexp',\n", " 'lgamma',\n", " 'log',\n", " 'log10',\n", " 'log1p',\n", " 'modf',\n", " 'pi',\n", " 'pow',\n", " 'radians',\n", " 'sin',\n", " 'sinh',\n", " 'sqrt',\n", " 'tan',\n", " 'tanh',\n", " 'trunc']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "\n", "dir(math)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Usando la función `help` podemos obtener una descripción de cada función (casi... no todas las funciones tienen *docstrings*, como se les llama técnicamente. Sin embargo, la mayoría de las funciones están documentadas de esta forma). " ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function log in module math:\n", "\n", "log(...)\n", " log(x[, base])\n", " \n", " Return the logarithm of x to the given base.\n", " If the base not specified, returns the natural logarithm (base e) of x.\n", "\n" ] } ], "source": [ "help(math.log)" ] }, { "cell_type": "code", "execution_count": 132, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2.302585092994046" ] }, "execution_count": 132, "metadata": {}, "output_type": "execute_result" } ], "source": [ "log(10) # calcula el logaritmo de 10 en base e" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3.3219280948873626" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "log(10, 2) # calcula el logaritmo de 10 en base 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También podemos usar la función `help` directamente sobre los módulos: \n", "\n", " help(math) \n", "\n", "Algunos módulos muy útiles de la librería estándar de Python son `os` (interfaz con el sistema operativo), `sys` (Parámetros y funciones específicas del sistema), `math` (funciones matem'aticas), `shutil` (operaciones con archivos), `subprocess`, `multiprocessing`, `threading`. \n", "\n", "Una lista completa de los módulos estándar para Python 2 y Python 3 está disponible (en inglés) en [http://docs.python.org/2/library/](http://docs.python.org/2/library/) y [http://docs.python.org/3/library/](http://docs.python.org/3/library/), respectivamente. Una versión en español está disponible en [http://pyspanishdoc.sourceforge.net/lib/lib.html](http://pyspanishdoc.sourceforge.net/lib/lib.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creación de Módulos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uno de los conceptos más importantes en programación es el de reusar código para evitar repeticiones.\n", "\n", "La idea es escribir funciones y clases con un propósito y extensión bien definidos, y reusarlas en lugar de repetir código similar en diferentes partes del programa (programación modular). Usualmente el resultado es que se mejora ostensiblemente la facilidad de lectura y de mantención de un programa. En la práctica, esto significa que nuestro programa tendrá menos errores, y serán más fáciles de extender y corregir. \n", "\n", "Python permite programación modular en diferentes niveles. Las funciones y las clases son ejemplos de herramientas para programación modular de bajo nivel. Los módulos Python son construcciones de programación modular de más alto nivel, donde podemos colectar variables relacionadas, funciones y clases. Un módulo Python es definido en un archivo Python (con extensión `.py`), y puede ser accequible a otros módulos Python y a programas usando el comendo `import`. \n", "\n", "Considere el siguiente ejemplo: el archivo `mimodulo.py` contiene una implementación simple de una variable, una función y una clase:" ] }, { "cell_type": "code", "execution_count": 119, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%more mimodulo.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos importar el módulo `mimodulo` a un programa Python usando `import`:" ] }, { "cell_type": "code", "execution_count": 120, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import mimodulo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use `help(module)` para obtener un resumen de lo que suministra el módulo:" ] }, { "cell_type": "code", "execution_count": 121, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on module mimodulo:\n", "\n", "NAME\n", " mimodulo\n", "\n", "FILE\n", " /home/gr/Dropbox/Git/clases-python-cientifico/mimodulo.py\n", "\n", "DESCRIPTION\n", " Ejemplo de un módulo Python. Contiene una variable llamada mi_variable,\n", " una función llamada mi_function, y una clase llamada MiClase.\n", "\n", "CLASSES\n", " MiClase\n", " \n", " class MiClase\n", " | Clase ejemplo.\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self)\n", " | \n", " | get_variable(self)\n", " | \n", " | set_variable(self, nuevo_valor)\n", " | Asigna self.variable a un nuevo valor\n", "\n", "FUNCTIONS\n", " mi_function()\n", " Función ejemplo\n", "\n", "DATA\n", " mi_variable = 0\n", "\n", "\n" ] } ], "source": [ "help(mimodulo)" ] }, { "cell_type": "code", "execution_count": 122, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 122, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mimodulo.mi_variable" ] }, { "cell_type": "code", "execution_count": 123, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mimodulo.mi_function() " ] }, { "cell_type": "code", "execution_count": 124, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mi_clase = mimodulo.MiClase() \n", "mi_clase.set_variable(10)\n", "mi_clase.get_variable()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si hacemos cambios en el código de `mimodulo.py`, necesitamos recargaro usando `reload`:" ] }, { "cell_type": "code", "execution_count": 125, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "reload(mimodulo) # sólo funciona en Python 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Excepciones\n", "\n", "En Python los errores son manejados con una construcción especial de lenguaje llamada \"Exceptions\" (excepciones). Cuando ocurre un error, una excepción puede ser hecha, que interrumpe el flujo normal del programa y retorna a algún otro lugar del código donde se definan los comandos try-except más cercanos.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para generar una excepción podemos usar el comando `raise`, que toma un argumento que debe ser una instancia de la clase `BaseExpection` o una clase derivada de ella. " ] }, { "cell_type": "code", "execution_count": 126, "metadata": { "collapsed": false }, "outputs": [ { "ename": "Exception", "evalue": "descripción del error", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mException\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"descripción del error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mException\u001b[0m: descripción del error" ] } ], "source": [ "raise Exception(\"descripción del error\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Un úso típico de las excepciones es para abortar funciones cuando ocurre algún error, por ejemplo:\n", "\n", " def mi_funcion(argumentos):\n", " \n", " if not verify(argumentos):\n", " raise Expection(\"Argumentos invalidos\")\n", " \n", " # el resto del código sigue aquí" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para capturar los errores que son generados por funciones y métodos de clases, o por el mismo intérprete Python, use los comandos `try` y `except`:\n", "\n", " try:\n", " # aquí va el código normal\n", " except:\n", " # el código para manejar el error va aquí\n", " # Este código no se ejecuta a menos que \n", " # el código de arriba genere un error\n", "\n", "Por ejemplo:" ] }, { "cell_type": "code", "execution_count": 127, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n", "Encontré una excepción\n" ] } ], "source": [ "try:\n", " print(\"test\")\n", " # genera un error: ya que la variable test no está definida\n", " print(test)\n", "except:\n", " print(\"Encontré una excepción\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para obtener información sobre un error, podemos accesar la instancia de clase `Exception` que describe la excepción usando por ejemplo:\n", "\n", " except Exception as e:" ] }, { "cell_type": "code", "execution_count": 128, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n", "Encontré una excepción:name 'test' is not defined\n" ] } ], "source": [ "try:\n", " print(\"test\")\n", " # genera un error: ya que la variable test no está definida\n", " print(test)\n", "except Exception as e:\n", " print(\"Encontré una excepción:\" + str(e))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lectura adicional\n", "\n", "* [http://www.python.org](http://www.python.org) - The official web page of the Python programming language.\n", "* [http://www.python.org/dev/peps/pep-0008](http://www.python.org/dev/peps/pep-0008) - Guía de estilo para la programación en Python. Altamente recomendada (en inglés).\n", "* [http://www.greenteapress.com/thinkpython/](http://www.greenteapress.com/thinkpython/) - Un libro gratuito sobre Python.\n", "* [Python Essential Reference](http://www.amazon.com/Python-Essential-Reference-4th-Edition/dp/0672329786) - Un buen libro de referencia sobre programación en Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Versiones" ] }, { "cell_type": "code", "execution_count": 129, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import sys\n", "import IPython" ] }, { "cell_type": "code", "execution_count": 130, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Este notebook fue evaluado con: Python 2.7.6 (default, Mar 22 2014, 22:59:56) \n", "[GCC 4.8.2] y IPython 2.1.0.\n" ] } ], "source": [ "print(\"Este notebook fue evaluado con: Python %s y IPython %s.\" % (sys.version, IPython.__version__))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 0 }