=============================== Introducción al lenguaje Python =============================== .. Conocer la sintaxis, las estructuras de datos y de control principales, las funciones más usadas y la creación de objetos para poder escribir y entender programas sencillos. Duración 4 horas. .. figure:: /_static/python-logo.png "Python" and the Python logos are trademarks or registered trademarks of the Python Software Foundation Intro ===== El Zen de Python ---------------- .. code:: text Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! Traducido... ------------ .. code:: text Hermoso es mejor que feo. Explícito es mejor que implícito. Simple es mejor que complejo. Complejo es mejor que complicado. Plano es mejor que anidado. Disperso es mejor que denso. La legibilidad cuenta. Los casos especiales no son lo suficiente como para romper las reglas. Aunque lo práctico vence a lo puro. Los errores no deben pasar desapercibidos. A menos que sean explícitamente silenciados. Ante la ambigüedad, rechaza la tentación de adivinar. Debe haber una - y preferiblemente solo una - manera obvia de hacerlo. Aunque puede no ser obvia a la primera si no eres holandés. Ahora es mejor que nunca. Aunque nunca es a menudo mejor que la ahora mismo. Si la implementación es difícil de explicar, es una mala idea. Si la aplicación es fácil de explicar, puede que sea una buena idea. Los *namespace* son una gran idea - hay que a hacer más! Características generales ------------------------- * Lenguaje dinámico pero fuertemente tipado * Consistencia de estilo es importante (`PEP 8 -- Style Guide for Python Code `_) * Interpretado (*) Anatomía de un programa ======================= Ejemplo ------- .. code:: python # Ejemplo programa en Python name = "Python" print(name) if name == "Python": print("Awesome!") Comentarios ----------- * Precedido por carácter ``#`` .. code:: python # Esto es un comentario * Se ignoran... salvo por herramientas .. code:: python a = None # noqa * No hay comentarios multilínea .. code:: python # Este es un comentario # que como es muy largo # tiene varias líneas Asignación ---------- * El operador de asignación es ``=`` .. code:: a = 1 Bloques ------- * **Sangría define los bloques**: alternativas en otros lenguajes (``{}``) o palabras clave (``begin..end``) * Siempre **cuatro espacios** .. testsetup:: * n = 42 .. testcode:: if n == 42: print('This is the answer') else: print('Try again') .. testoutput:: This is the answer Control de flujo ---------------- - ``if``, ``elif`` y ``else`` - ``while`` - ``for``, ``break`` y ``continue`` Otros ----- - ``pass``, no operación .. code:: python >>> while True: ... pass ... ^CTraceback (most recent call last): File "", line 1, in KeyboardInterrupt >>> Funciones --------- .. code:: python def div(a, b): return a / b Identificadores válidos ----------------------- - Comienza con una letra (A-Za-z) o con un guion bajo (_) - Seguido de cero o más letras, guiones bajos y números - Distingue mayúsculas de minúsculas - No se permiten signos de puntuación - Prohibidas palabras reservadas: `if`, `while`, `for`... Convenio nombres (variables, funciones, clases...) -------------------------------------------------- **snake_case** Variables y funciones en general **SCREAMING_SNAKE_CASE** Constantes **CamelCase** Clases **_underscore** Indica uso interno **__dunder__** Especial uso dentro del lenguaje (*mágicos*) Funciones incluidas en el lenguaje ================================== Librería estándar ----------------- .. figure:: /_static/python-builtin-functions.png * 71 funciones siempre disponibles (`documentación `_) Ejemplos -------- ``type(object)`` Devuelve el tipo de un objeto. ``print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)`` Imprime los objetos indicados. *Constructores* --------------- Funciones que devuelven nuevos objetos: - ``object`` - ``bool`` - ``int`` - ``float`` - ``str`` - ``bytearray`` y ``bytes`` - ``list`` y ``tuple`` - ``set`` y ``frozenset`` - ``dict`` - ``complex`` Tipos estándar ============== .. Ver https://docs.python.org/3/library/stdtypes.html Booleano -------- Verdadero o falso. Es el resultado de las comparaciones. .. doctest:: >>> 1 == 1 True >>> 1 == 0 False >>> type(True) .. nextslide:: :increment: Son falsos: .. doctest:: >>> False False >>> bool(None) False >>> bool(0) False >>> bool(0.0) False >>> bool("") False >>> bool([]) False Booleano: operadores -------------------- ============ ========= Operación Resultado ============ ========= ``x and y`` Y lógico ``x or y`` O lógico ``not x`` negación ============ ========= Booleano: operadores de comparación ----------------------------------- ========== ========= Operación Resultado ========== ========= ``<`` estrictamente menor ``<=`` menor o igual ``>`` estrictamente mayor ``>=`` mayor o igual ``==`` igual ``!=`` no igual ``is`` identidad de objetos ``is not`` identidad de objetos negada ========== ========= None ---- Valor nulo. .. doctest:: >>> None >>> type(None) Numéricos --------- .. doctest:: >>> type(1) >>> type(1.0) >>> type(1/2) ========= ========= Operación Resultado ========= ========= ``x + y`` Suma ``x - y`` Resta ``x * y`` Multiplicación ``x / y`` División ``x % y`` Resto ``-x`` Opuesto ========= ========= Numéricos: otros operadores --------------------------- ================ ========= Operación Resultado ================ ========= ``x // y`` División entera ``pow(x, y)`` *x* elevado a *y* ``x ** y`` *x* elevado a *y* ``divmod(x, y)`` Devuelve ``(x // y, x % y)`` ``abs(x)`` Valor absoluto ================ ========= - Otros: números, complejos, decimal... Funciones numéricas ------------------- ``abs(x)`` Devuelve el valor absoluto de un número. ``divmod(a, b)`` Devuelve dos números que se corresponden con el cociente y el resto de dividir ``a`` entre ``b``. Es equivalente a la expresión ``(a // b, a % b)``. ``pow(x, y[, z])`` Devuelve ``x`` elevado a la ``y`` potencia. Si se especifica ``z`` se calcula ``x`` elevado a ``y`` módulo ``z``. ``round(number[, digits])`` Devuelve ``number`` redondeado con el número de decimales indicado por ``digits``, 0 si no se especifica. Secuencias ---------- .. doctest:: >>> fibonacci = (0, 1, 1, 2, 3, 5) >>> type(fibonacci) >>> primos = [0, 1, 2, 3, 5, 7] >>> type(primos) .. _sequence-operations: +--------------------------+ | Operación | +==========================+ | ``x in s`` | +--------------------------+ | ``x not in s`` | +--------------------------+ | ``s + t`` | +--------------------------+ | ``s * n`` or ``n * s`` | +--------------------------+ Secuencias: índices y *slicing* ------------------------------- .. figure:: /_static/python-slicing-index.png .. doctest:: >>> s = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] >>> s[2] 'c' >>> s[0:2] ['a', 'b'] >>> s[1:-1] ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] >>> s[1:-1:2] ['b', 'd', 'f', 'h'] Secuencias: índices y *slicing* ------------------------------- ======================== ========= Operación Resultado ======================== ========= ``s[i]`` Índice ``s[i:j]`` *Slice* ``s[i:j:k]`` *Slice* con un paso ``len(s)`` Longitud ``min(s)`` Mínimo ``max(s)`` Máximo ``s.index(x[, i[, j]])`` Busca ``x`` y devuelve índice ``s.count(x)`` Número de ocurrencias ======================== ========= Secuencias: mutables/inmutables ------------------------------- :class:`list` es un tipo de objeto **mutable**, :class:`tuplas` son **inmutables**. Las listas soportan operaciones que modifican el objeto directamente en el mismo espacio de memoria. =============== ========= Operación Resultado =============== ========= ``s[i] = x`` reemplaza el elemento *i* de *s* con *x* ``s[i:j] = t`` reemplaza porción de *s* de *i* a *j* con *t* ``del s[i:j]`` borra porción (equivale a ``s[i:j] = []``) =============== ========= Secuencias: operaciones sobre listas ------------------------------------ ============================= =============================== Operación Resultado ============================= =============================== ``s.append(x)`` añade *x* a la secuecia *s* ``s.extend(t)`` extiende *s* con el contenido de *t* ``s.insert(i, x)`` inserta *x* en *s* en la posición *i* ``s.pop([i])`` recupera el elemento en *i* y también lo elimina de *s* ``s.remove(x)`` borra el primer elemento de *s* tal que ``s[i] == x`` ``s.reverse()`` invierte los elementos de *s* ============================= =============================== Secuencias de texto ------------------- .. doctest:: >>> type('¡Hola mundo!') Se pueden utilizar tanto comillas simples como comillas dobles. .. doctest:: >>> "It's ok" "It's ok" >>> 'El lenguaje se llama así como homenaje a los "Monty Python"' 'El lenguaje se llama así como homenaje a los "Monty Python"' Secuencias de texto: ``"`` y ``'`` ---------------------------------- Triple comillas para incluir saltos de línea y espacios .. doctest:: >>> poem = """ ... Que toda la vida es sueño ... y los sueños ... sueños son.""" >>> poem '\n Que toda la vida es sueño\n y los sueños\n sueños son.' Secuencias de texto: códigos de escape -------------------------------------- ====== ======= Escape Valor ====== ======= ``\n`` Salto de línea ``\t`` Tabulador ``\\`` Contra barra (\\) ``\'`` Comilla simple (``'``) ``\"`` Comilla doble (``"``) ====== ======= Secuencias de texto: Operaciones -------------------------------- Son secuencias inmutables (como :class:`tuple`) y por eso soportan :ref:`las mismas operaciones `. ================================= ===== Operación Resultado ================================= ===== ``str.lower()`` y ``str.upper()`` Minúsculas/mayúsculas ``str.strip([chars])`` Elimina *chars* al principio y al final ``str.join(iterable)`` Concatena *iterable* usando *str* como pegamento ``str.split([sep[, maxsplit]])`` Divide *str* usando *sep* como delimitador ================================= ===== Secuencias binarias ------------------- .. doctest:: >>> type(b'ABC') >>> type(bytearray(b'ABC')) :class:`bytes` son secuencias de bytes :class:`bytearray` lo mismo pero mutable Secuencias de binarias: bytes ----------------------------- * Prefijo ``b''`` * Se pueden ver como una secuencia de enteros de 0 a 255 .. doctest:: >>> b = bytes([0, 1, 254, 255]) >>> b b'\x00\x01\xfe\xff' >>> b[-1] 255 >>> b[1:3] b'\x01\xfe' Conjuntos --------- .. doctest:: >>> type({0, 1, 1, 2, 3, 5}) >>> type(frozenset({0, 1, 1, 2, 3, 5})) :class:`set` es un conjunto de elementos :class:`frozenset` es un conjunto pero **inmutable** Conjuntos: operaciones ---------------------- ============================== ====== Operación Resultado ============================== ====== set.issubset(other) Comprueba que cada elemento de *set* está en *other* set.issuperset(other) Comprueba que cada elemento de *other* está en *set* set.union(other, ...) Nuevo conjunto con todos los elementos set.intersection(other, ...) Nuevo conjunto con la intersección set.difference(other, ...) Nuevo conjunto con los elemento de *set* que no están en los otros ============================== ====== Diccionarios ------------ .. doctest:: >>> type({'key': 'value'}) :class:`dict` es un diccionario, mapa o array asociativo Es **mutable** Diccionarios: operaciones básicas --------------------------------- ================== ========= Operación Resultado ================== ========= ``len(d)`` Número de elementos ``d[key]`` Valor de la clave *key* ``d[key] = value`` Fija el valor de *key* a *value* ``del d[key]`` Borra clave *key* ``key in d`` *True* si existe la clave *key* ``key not in d`` Equivalente a ``not key in d`` ================== ========= Diccionarios: operaciones de actualización ------------------------------------------ ================================ ========= Operación Resultado ================================ ========= ``d.get(key[, default])`` Devuelve valor clave *key* o *default* si no existe ``d.pop(key[, default])`` Si la clave *key* existe, la borra y devuelve el valor. Si no devuelve *default* ``d.setdefault(key[, default])`` Si *key* existe devuelve su valor. Si no inserta valor *default* y devuelve *default* ``d.update([other])`` Actualiza el diccionario con las claves/valores de *other* ================================ ========= Diccionarios: recorrer elementos -------------------------------- ================================ ========= Operación Resultado ================================ ========= ``d.keys()`` Vista con las claves ``d.values()`` Vista con los valores ``d.items()`` Vista con el par clave/valor ================================ ========= Archivos y flujos de entrada/salida =================================== *file* ------ * archivo del sistema operativo. * se crea con ``open()`` .. doctest:: file >>> f = open('sample.txt') >>> type(f) >>> f.close() file: modos ----------- Modos: - ``'r'`` lectura (por defecto) - ``'w'`` escritura - ``'a'`` adición Además: - ``'t'`` texto (por defecto) - ``'b'`` binario .. testsetup:: file f = open('sample.txt', 'w') f.close() file: modo texto ---------------- * Por defecto * Se encarga de saltos de línea según plataforma (``\n`` → CRLF o LF) * Incluye codificación (ISO-8859-1, UTF-8, ...) file: modo texto ---------------- .. doctest:: file >>> f = open('toys.txt', mode='w') >>> f.write('Mis favoritos son\n') 18 >>> f.write('- Buzz\n') 7 >>> f.write('- Woody\n\n') 9 >>> f.close() .. testsetup:: file-text with open('toys.txt', mode='w') as f: f.writelines(['Mis favoritos son\n', '- Buzz\n', '- Woody\n', '\n']) .. doctest:: file-text >>> f = open('toys.txt', mode='r') >>> for l in f: ... print(repr(l)) ... ... 'Mis favoritos son\n' '- Buzz\n' '- Woody\n' '\n' >>> f.close() file: modo binario ------------------ .. testsetup:: file-binary with open('sample.bin', 'wb') as f: f.write(b'\x00\xFF') .. doctest:: file-binary >>> f = open('sample.bin', 'wb') >>> type(f) >>> f.write('a') Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface >>> f.write(b'\x00\xFF') 2 >>> f.close() .. doctest:: file-binary >>> f = open('sample.bin', 'rb') >>> for b in f: ... print(repr(b)) ... ... b'\x00\xff' Funciones ========= Funciones: valores por defecto ------------------------------ .. code:: python def div(a, b=2): return a / b .. testsetup:: * def div(a, b=2): return a / b .. doctest:: >>> div(8, 2) 4.0 >>> div(8) 4.0 >>> div(a=8, b=2) 4.0 >>> div(b=2, a=8) 4.0 Clases e instancias =================== Clases: definición ------------------ .. code:: class Nombredeclase: expresión 1 expresión 2 . . expresión N .. code:: python class Circle: PI = 3.14 def __init__(self, radius): self.radius = radius def perimeter(self): return 2 * self.PI * self.radius Clases: uso ----------- .. testsetup:: class Circle: PI = 3.14 def __init__(self, radius): self.radius = radius def perimeter(self): return 2 * self.PI * self.radius .. doctest:: >>> Circle.PI 3.14 >>> a_circle = Circle(3) >>> a_circle.radius 3 >>> a_circle.perimeter() 18.84 Errores y excepciones ===================== Exception --------- .. doctest:: >>> f = open('non-existing-file') Traceback (most recent call last): File "", line 1, in FileNotFoundError: [Errno 2] No such file or directory: 'non-existing-file' .. doctest:: >>> try: ... f = open('non-existing-file') ... except FileNotFoundError: ... print('Sorry, file not exist') ... ... Sorry, file not exist >>> Excepciones: captura distintas ------------------------------ .. doctest:: >>> values = ["x", None] >>> for value in values: ... try: ... r = int(value) ... except TypeError: ... print("Tipo no compatible") ... except ValueError: ... print("Error al convertir el valor") ... Error al convertir el valor Tipo no compatible Excepciones: lanzando excepciones --------------------------------- .. code:: python >>> raise SyntaxError('Revisa el programa, por favor') Traceback (most recent call last): File "", line 1, in File "", line None SyntaxError: Revisa el programa, por favor .. code:: python >>> try: ... a = 1 / 0 ... except ZeroDivisionError: ... print('I do not know how to divide by zero') ... raise ... I do not know how to divide by zero Traceback (most recent call last): File "", line 2, in ZeroDivisionError: division by zero Excepciones: else ----------------- - bloque ``else`` se ejecuta si no se lanza ninguna excepción en el bloque try >>> try: ... a = 1 / 1 ... except ZeroDivisionError: ... print('I do not know how to divide by zero') ... else: ... print('No error') ... No error Excepciones: finally -------------------- - bloque ``finally`` siempre se ejecuta .. code:: python >>> try: ... a = 1 / 0 ... except ZeroDivisionError: ... print('I do not know how to divide by zero') ... finally: ... print('Disconnecting...') ... ... I do not know how to divide by zero Disconnecting... .. nextslide:: .. code:: python >>> try: ... a = 1 / 1 ... except ZeroDivisionError: ... print('I do not know how to divide by zero') ... else: ... print('No error') ... finally: ... print('Disconnecting...') ... ... No error Disconnecting... Módulos y paquetes ================== Módulos ------- .. literalinclude:: ../geometry.py Módulos: import --------------- .. code:: python >>> import geometry >>> c = geometry.Circle(1.0) >>> print(c) .. code:: python >>> import geometry as g >>> c = g.Circle(1.0) >>> print(c) .. code:: python >>> from geometry import Circle >>> c = Circle(1.0) >>> print(c) .. code:: python >>> from geometry import * >>> PI 3.1415 Paquetes: carpetas ------------------ .. code:: graphics/ ├── __init__.py ├── colors.py └── shapes.py .. literalinclude:: ../graphics/__init__.py .. literalinclude:: ../graphics/colors.py Paquetes: carpetas ------------------ ... .. literalinclude:: ../graphics/shapes.py Paquetes: import ---------------- .. code:: python >>> import graphics >>> graphics.PI 3.1415 >>> import graphics.colors >>> graphics.colors.Red >>> graphics.colors.Red.css '#F00' .. nextslide:: :increment: .. code:: python >>> from graphics import shapes >>> c = shapes.Circle(1.0) >>> print(c) .. nextslide:: :increment: .. code:: python >>> from graphics.shapes import Circle >>> c = Circle(1.0) >>> print(c)