Introducción al lenguaje Python

../_images/python-logo.png

«Python» and the Python logos are trademarks or registered trademarks of the Python Software Foundation

Intro

El Zen de Python

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…

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

Anatomía de un programa

Ejemplo

# Ejemplo programa en Python
name = "Python"
print(name)
if name == "Python":
    print("Awesome!")

Comentarios

  • Precedido por carácter #

    # Esto es un comentario
    
  • Se ignoran… salvo por herramientas

    a = None  # noqa
    
  • No hay comentarios multilínea

    # Este es un comentario
    # que como es muy largo
    # tiene varias líneas
    

Asignación

  • El operador de asignación es =

    a = 1
    

Bloques

  • Sangría define los bloques: alternativas en otros lenguajes ({}) o palabras clave (begin..end)

  • Siempre cuatro espacios

if n == 42:
    print('This is the answer')
else:
    print('Try again')
This is the answer

Control de flujo

  • if, elif y else

  • while

  • for, break y continue

Otros

  • pass, no operación

>>> while True:
...     pass
...
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>>

Funciones

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

../_images/python-builtin-functions.png

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

Booleano

Verdadero o falso. Es el resultado de las comparaciones.

>>> 1 == 1
True
>>> 1 == 0
False
>>> type(True)
<class 'bool'>

Son falsos:

>>> 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.

>>> None
>>> type(None)
<class 'NoneType'>

Numéricos

>>> type(1)
<class 'int'>
>>> type(1.0)
<class 'float'>
>>> type(1/2)
<class 'float'>

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

>>> fibonacci = (0, 1, 1, 2, 3, 5)
>>> type(fibonacci)
<class 'tuple'>
>>> primos = [0, 1, 2, 3, 5, 7]
>>> type(primos)
<class 'list'>

Operación

x in s

x not in s

s + t

s * n or n * s

Secuencias: índices y slicing

../_images/python-slicing-index.png
>>> 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

list es un tipo de objeto mutable, 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

>>> type('¡Hola mundo!')
<class 'str'>

Se pueden utilizar tanto comillas simples como comillas dobles.

>>> "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

>>> 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 tuple) y por eso soportan 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

>>> type(b'ABC')
<class 'bytes'>
>>> type(bytearray(b'ABC'))
<class 'bytearray'>

bytes son secuencias de bytes

bytearray lo mismo pero mutable

Secuencias de binarias: bytes

  • Prefijo b''

  • Se pueden ver como una secuencia de enteros de 0 a 255

>>> b = bytes([0, 1, 254, 255])
>>> b
b'\x00\x01\xfe\xff'
>>> b[-1]
255
>>> b[1:3]
b'\x01\xfe'

Conjuntos

>>> type({0, 1, 1, 2, 3, 5})
<class 'set'>
>>> type(frozenset({0, 1, 1, 2, 3, 5}))
<class 'frozenset'>

set es un conjunto de elementos

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

>>> type({'key': 'value'})
<class 'dict'>

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()

>>> f = open('sample.txt')
>>> type(f)
<class '_io.TextIOWrapper'>
>>> f.close()

file: modos

Modos:

  • 'r' lectura (por defecto)

  • 'w' escritura

  • 'a' adición

Además:

  • 't' texto (por defecto)

  • 'b' binario

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

>>> 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()
>>> 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

>>> f = open('sample.bin', 'wb')
>>> type(f)
<class '_io.BufferedWriter'>
>>> f.write('a')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'str' does not support the buffer interface
>>> f.write(b'\x00\xFF')
2
>>> f.close()
>>> f = open('sample.bin', 'rb')
>>> for b in f:
...     print(repr(b))
...
...
b'\x00\xff'

Funciones

Funciones: valores por defecto

def div(a, b=2):
    return a / b
>>> 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

class Nombredeclase:
    expresión 1
    expresión 2
    .
    .
    expresión N
class Circle:
    PI = 3.14

    def __init__(self, radius):
        self.radius = radius

    def perimeter(self):
        return 2 * self.PI * self.radius

Clases: uso

>>> Circle.PI
3.14
>>> a_circle = Circle(3)
>>> a_circle.radius
3
>>> a_circle.perimeter()
18.84

Errores y excepciones

Exception

>>> f = open('non-existing-file')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'non-existing-file'
>>> try:
...     f = open('non-existing-file')
... except FileNotFoundError:
...     print('Sorry, file not exist')
...
...
Sorry, file not exist
>>>

Excepciones: captura distintas

>>> 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

>>> raise SyntaxError('Revisa el programa, por favor')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<string>", line None
SyntaxError: Revisa el programa, por favor
>>> 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 "<input>", line 2, in <module>
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

>>> 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...
>>> 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

# geometry.py

PI = 3.1415

class Circle:
    def __init__(self, radius):
        self.radius = radius

class Square:
    def __init__(self, side):
        self.side = side

class Rectangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height

Módulos: import

>>> import geometry
>>> c = geometry.Circle(1.0)
>>> print(c)
<geometry.Circle object at 0x7f699fd05f28>
>>> import geometry as g
>>> c = g.Circle(1.0)
>>> print(c)
<geometry.Circle object at 0x7f699fd05f28>
>>> from geometry import Circle
>>> c = Circle(1.0)
>>> print(c)
<geometry.Circle object at 0xb7453e2c>
>>> from geometry import *
>>> PI
3.1415

Paquetes: carpetas

graphics/
├── __init__.py
├── colors.py
└── shapes.py
# __init__.py
PI = 3.1415
# colors.py
class Red:
    css = '#F00'

class Green:
    css = '#0F0'

class Blue:
    css = '#00F'

Paquetes: carpetas

# shapes.py
class Circle:
    def __init__(self, radius):
        self.radius = radius

class Square:
    def __init__(self, side):
        self.side = side

class Rectangle:
    def __init__(self, base, height):
        self.base = base
        self.height = height

Paquetes: import

>>> import graphics
>>> graphics.PI
3.1415
>>> import graphics.colors
>>> graphics.colors.Red
<class 'graphics.colors.Red'>
>>> graphics.colors.Red.css
'#F00'
>>> from graphics import shapes
>>> c = shapes.Circle(1.0)
>>> print(c)
<graphics.shapes.Circle object at 0x7f1515eab668>
>>> from graphics.shapes import Circle
>>> c = Circle(1.0)
>>> print(c)
<graphics.shapes.Circle object at 0x7f1515eab668>