Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


PYTHON NO MUERDE......, Diapositivas de Tecnología

LA manera mas facil de aprender programacion

Tipo: Diapositivas

2019/2020

Subido el 12/11/2020

anamagu
anamagu 🇨🇴

5

(1)

4 documentos

1 / 97

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Python no muerde Documentation
Versión 2.0
Roberto Alsina (actualización por Martín Gait
05 de noviembre de 2017
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61

Vista previa parcial del texto

¡Descarga PYTHON NO MUERDE...... y más Diapositivas en PDF de Tecnología solo en Docsity!

Python no muerde Documentation

Versión 2.

Roberto Alsina (actualización por Martín Gait

05 de noviembre de 2017

II

Autor Roberto Alsina

Versión $Revision: 8e80f80bdea9 $

Índice general 1

CAPÍTULO 1

Introducción

1.1 Requisitos

Éste es un libro sobre Python^1. Es un libro que trata de explicar una manera posible de usarlo, una manera de tomar

una idea de tu cabeza y convertirla en un programa, que puedas usar y compartir.

¿Qué necesitás saber para poder leer este libro?

El libro no va a explicar la sintaxis de python, sino que va a asumir que la conocés. De todas formas, la primera vez

que aparezca algo nuevo, va a indicar dónde se puede aprender más sobre ello. Por ejemplo:

Creamos una lista con los cuadrados de los números pares

cuadrados = [ x**2 for x in numeros if x%2 == 0 ]

Referencia

Eso es una comprensión de lista

En general esas referencias van a llevarte al Tutorial de Python en castellano. Ese libro contiene toda la información

acerca del lenguaje que se necesita para poder seguir éste.

Cuando una aplicación requiera una interfaz gráfica, vamos a utilizar PyQt^2. No vamos a asumir ningún conocimiento

previo de PyQt pero tampoco se va a explicar en detalle, excepto cuando involucre un concepto nuevo.

Por ejemplo, no voy a explicar el significado de setEnabled^3 pero sí el concepto de signals y slots cuando haga

falta.

(^1) ¿Por qué Python? Porque es mi lenguaje favorito. ¿De qué otro lenguaje podría escribir? (^2) PyQt es software libre, es multiplataforma, y es muy potente y fácil de usar. Eso no quiere decir que las alternativas no tengan las mismas características, pero quiero enfocarme en programar, no en discutir, y yo prefiero PyQt. Si preferís una alternativa, este libro es libre: podés hacer una versión propia! (^3) PyQt tiene una excelente documentación de referencia para esas cosas.

1.2 Convenciones

Las variables, funciones y palabras reservadas de python se mostrarán en el texto con letra monoespaciada. Por ejem-

plo, for es una palabra reservada.

Los fragmentos de código fuente se va a mostrar así:

Creamos una lista con los cuadrados de los números impares

cuadrados = [ x**2 for x in numeros if x%2 > 0 ]

Los listados extensos o programas completos se incluirán sin cajas, mostrarán números de líneas e indicarán el nombre

del mismo:

titulo-listado

cuadrados.py

class listado

1 # Creamos una lista con los cuadrados de los números impares 2 cuadrados = [ x**2 for x in numeros if x%2 > 0 ]

En ese ejemplo, debería haber, en los ejemplos que acompañan al libro, un archivo codigo/X/cuadrados.py

donde X es el número del capítulo en el que el listado aparece.

1.3 Lenguaje

Las discusiones acerca de como escribir un libro técnico en castellano son eternas. Que en España se traduce todo todo

todo. Que en Argentina no. Que decir “cadena de caracteres” en lugar de string es malo para la ecología.

Por suerte en este libro hay un único criterio superador que ojalá otros libros adopten: Está escrito como escribo yo.

Ni un poquito distinto. No creo que siquiera califique como castellano, como mucho está escrito en argentino. Si a los

lectores de la ex madre patria les molesta el estilo... tradúzcanlo.

1.4 Mapa

Dentro de lo posible, voy a intentar que cada capítulo sea autocontenido, explicando un tema sin depender demasiado

de los otros, y terminando con un ejemplo concreto y funcional.

Éstos son los capítulos del libro, con breves descripciones.

1. Introducción

2. Pensar en python

Programar en python, a veces, no es como programar en otros lenguajes. Acá vas a ver algunos ejemplos. Si te

gustan... python es para vos. Si no te gustan... bueno, el libro es barato... capaz que Java es lo tuyo..

3. La vida es corta

Por eso, hay muchas cosas que no vale la pena hacer. Claro, yo estoy escribiendo un editor de textos así que este

capítulo es pura hipocresía...

4. Las capas de una aplicación

Batman, los alfajores santafesinos, el ozono... las mejores cosas tienen capas. Cómo organizar una aplicación en

capas.

4 Capítulo 1. Introducción

dependencias.graph.pdf

Figura 1.1: Este libro se lee siguiendo las flechas.

Nuestra misión en este capítulo es pensar en qué quiere decir Eby con “código python idiomático” en esa cita. Nunca

nadie va a poder hacer un pythonómetro que te mida cuán idiomático es un fragmento de código, pero es posible

desarrollar un instinto, una “nariz” para sentir el “olor a python”, así como un enófilo^1 aprende a distinguir el aroma a

clavos de hierro-níquel número 7 ligeramente oxidados en un Cabernet Sauvignon.^2

Y si la mejor forma de conocer el vino es tomar vino, la mejor forma de conocer el código es ver código. Este capítulo

no es exhaustivo, no muestra todas las maneras en que python es peculiar, ni todas las cosas que hacen que tu código

sea “pythonic” – entre otros motivos porque no las conozco – pero muestra varias. El resto es cuestión de gustos.

Get/Set

Una instancia de una clase contiene valores. ¿Cómo se accede a ellos? Hay dos maneras. Una es con “getters y setters”,

y estas son algunas de sus manifestaciones:

Un getter te "toma" (get) un valor de adentro de un objeto y

se puede ver así:

x1 = p.x() x1 = p.get_x() x1 = p.getX()

Un setter "mete" un valor en un objeto y puede verse así:

p.set_x(x1) p.setX(x1)

Otra manera es simplemente usar un miembro x de la clase:

p.x = x x1 = p.x

(^1) En mi barrio los llamábamos curdas. (^2) Con la esperanza de ser un poco menos pretencioso y/o chanta, si Zeus quiere.

6 Capítulo 1. Introducción

La ventaja de usar getters y setters es el “encapsulamiento”. No dicta que la clase tenga un miembro x, tal vez el valor

que yo ingreso via setX es manipulado, validado, almacenado en una base de datos, o tatuado en el estómago de

policías retirados con problemas neurológicos, lo único que importa es que luego cuando lo saco con el getter me dé

lo que tenga que dar (que no quiere decir “me dé lo mismo que puse”).

Muchas veces, los getters/setters se toman como un hecho de la vida, hago programación orientada a objetos => hago

getters/setters.

Bueno, no.

Analogía rebuscada

En un almacén, para tener un paquete de yerba, hay que pedírselo al almacenero. En un supermercado, para tener un

paquete de yerba, hay que agarrar un paquete de yerba. En una farmacia (de las grandes), para obtener un paquete de

yerba hay que agarrar un paquete de yerba, pero para tener un Lexotanil hay que pedirlo al farmacéutico.

En Java o C++, la costumbre es escribir programas como almacenes, porque la alternativa es escribir supermercados

donde chicos de 5 compran raticida.

En Python, la costumbre es escribir programas como supermercados, porque se pueden convertir en farmacias apenas

decidamos que tener raticida es buena idea.

Imaginemos que estamos escribiendo un programa que trabaja con “puntos” o sea coordenadas (X,Y), y que queremos

implementarlos con una clase. Por ejemplo:

titulo-listado

Listado 1

class listado

1 class Punto (object): 2 def init(self, x=0, y=0): 3 self.set_x(x) 4 self.set_y(y) 5 6 def x(self): 7 return self._x 8 9 def y(self): 10 return self._y 11 12 def set_x(self,x): 13 self._x=x 14 15 def set_y(self,y): 16 self._y=y

Esa es una implementación perfectamente respetable de un punto. Guarda X, guarda Y, permite volver a averiguar sus

valores... el problema es que eso no es python. Eso es C++. Claro, un compilador C++ se negaría a procesarlo, pero a

mí no me engañan tan fácil, eso es C++ reescrito para que parezca python.

¿Por qué eso no es python? Por el obvio abuso de los métodos de acceso (accessors, getter/setters), que son completa-

mente innecesarios.

Si la clase punto es simplemente esto, y nada más que esto, y no tiene otra funcionalidad, entonces prefiero esta:

titulo-listado

Listado 2

1.5. Acerca del Autor 7

4 def set_x(self, x): 5 self._x = abs(x)

Pero... también es fácil de hacer en el listado 2, sin cambiar la interfaz que se presenta al usuario:

titulo-listado

Listado 5

class listado

1 class PuntoDerecho (object): 2 '''Un punto que solo puede estar a la derecha del eje Y''' 3 4 def get_x(self): 5 return self._x 6 7 def set_x(self, x): 8 self._x = abs(x) 9 10 x = property(get_x, set_x)

Obviamente esto es casi lo mismo que si partimos del listado 1, pero con algunas diferencias:

La forma de acceder a x o de modificarlo es mejor – print p.x en lugar de print p.x(). Sí, es cuestión

de gustos nomás.

No se hicieron los métodos para y por ser innecesarios.

Esto es importante: de ser necesarios esos métodos en el futuro es fácil agregarlos. Si nunca lo son, entonces el

listado 1 tiene dos funciones inútiles.

Sí, son dos funciones cortas, que seguramente no crean bugs pero tienen implicaciones de performance, y tienen

un efecto que a mí personalmente me molesta: separan el código que hace algo metiendo en el medio código

que no hace nada.

Si esos métodos son funcionalmente nulos, cada vez que están en pantalla es como una franja negra de censura

de 5 líneas de alto cruzando mi editor. Es molesto.

Singletons

En un lenguaje funcional, uno no necesita patrones de diseño porque el lenguaje es de tan alto nivel que

terminás programando en conceptos que eliminan los patrones de diseño por completo.

—Slava Akhmechet

Una de las preguntas más frecuentes de novicios en python, pero con experiencia en otros lenguajes es “¿cómo hago

un singleton?”. Un singleton es una clase que sólo puede instanciarse una vez. De esa manera, uno puede obtener esa

única instancia simplemente reinstanciando la clase.

Hay varias maneras de hacer un singleton en python, pero antes de eso, dejemos en claro qué es un singleton: un

singleton es una variable global “lazy”.

En este contexto “lazy” quiere decir que hasta que la necesito no se instancia. Excepto por eso, no habría diferencias

visibles con una variable global.

El mecanismo “obvio” para hacer un singleton en python es un módulo, que son singletons porque así están imple-

mentados.

Ejemplo:

1.5. Acerca del Autor 9

>>> import os >>> os.x= >>> os.x 1 >>> import os as os >>> os2.x 1 >>> os2.x= >>> os.x 4 >>>

No importa cuantas veces importe os (o cualquier otro módulo), no importa con qué nombre lo haga, siempre es el

mismo objeto.

Por lo tanto, podríamos poner todos nuestros singletons en un módulo (o en varios) e instanciarlos con import y

funciones dentro de ese módulo.

Ejemplo:

titulo-listado

singleton1.py

class listado

>>> import singleton >>> uno=singleton1.misingle() >>> dos=singleton1.misingle() >>> print uno [] >>> uno.append('xx') >>> print dos ['xx']

Como pueden ver, uno y dos son el mismo objeto.

Una alternativa es no usar un singleton, sino lo que Alex Martelli llamó un Borg:

class Borg : __shared_state = {} def init(self): self.dict = self.__shared_state

¿Cómo funciona?

>>> a=Borg() >>> b=Borg() >>> a.x= >>> print b.x 1

Si bien a y b no son el mismo objeto por lo que no son realmente singletons, el efecto final es el mismo.

Por último, si andás con ganas de probar magia más potente, es posible hacer un singleton usando metaclases, según

esta receta de Andres Tuells:

1 ## {{{ http://code.activestate.com/recipes/102187/ (r1) 2 """ 3 USAGE:

10 Capítulo 1. Introducción

Repetirse es malo.

—Anónimo

Hay una estructura de control que Knuth llama el “loop n y medio” (n-and-half loop). Es algo así:

loop-n-y-medio.graph.pdf

Figura 1.2: ¡Se sale por el medio! Como siempre se pasa al menos por una parte del loop (A), Knuth le puso “loop n y

medio”.

Ésta es la representación de esta estructura en Python:

while True: frob(gargle)

Cortamos?

if gargle.blasted:

Cortamos!

break refrob(gargle)

No, no quiero que me discutan. Ésa es la forma de hacerlo. No hay que tenerle miedo al break! En particular la

siguiente forma me parece mucho peor:

frob(gargle)

Seguimos?

while not gargle.blasted: refrob(gargle) frob(gargle)

Es más propensa a errores. Antes, podía ser que frob(gargle) no fuera lo correcto. Ahora no solo puede ser

incorrecto, sino que puede ser incorrecto o inconsistente, si cambio solo una de las dos veces que se usa.

Claro, en un ejemplo de juguete esa repetición no molesta. En la vida real, tal vez haya 40 líneas entre una y otra y no

sea obvio que esa línea se repite.

Switches

Hay una cosa que muchas veces los que programan en Python envidian de otros lenguajes... switch (o case).

12 Capítulo 1. Introducción

Sí, Python no tiene un “if multirrama” ni un “goto computado” ni nada de eso. Pero ... hay maneras y maneras de

sobrevivir a esa carencia.

Esta es la peor:

if codigo == 'a': return procesa_a() if codigo == 'b': return procesa_b() : : etc.

Esta es apenas un cachito mejor:

if codigo == 'a': return procesa_a() elif codigo == 'b': return procesa_b() : : etc.

Esta es la buena:

procesos = { 'a': procesa_a, 'b': procesa_b, : : etc. }

return procesoscodigo

Al utilizar un diccionario para clasificar las funciones, es mucho más eficiente que una cadena de if. Es además

muchísimo más fácil de mantener (por ejemplo, podríamos poner procesos en un módulo separado).

Patos y Tipos

“Estás en un laberinto de pasajes retorcidos, todos iguales.”

—Will Crowther en “Adventure”

“Estás en un laberinto de pasajes retorcidos, todos distintos.”

—Don Woods en “Adventure”

Observemos este fragmento de código:

def diferencia(a,b):

Devuelve un conjunto con las cosas que están

en A pero no en B

return set(a) - set(b)

Set

1.5. Acerca del Autor 13

Genéricos

Supongamos que necesito poder crear listas con cantidades arbitrarias de objetos, todos del mismo tipo, inicializados

al mismo valor.

Comprensión de lista

En las funciones que siguen, [tipo() for i in range(cantidad)] se llama una comprensión de lista, y

es una forma más compacta de escribir un for para generar una lista a partir de otra:

resultado=[] for i in range(cantidad): resultado.append(tipo())

No conviene utilizarlo si la expresión es demasiado complicada.

Ver también: Listas por comprensión en el tutorial de Python

Un enfoque ingenuo podría ser este:

def listadestr(cantidad): return ['' for i in range(cantidad)]

def listadeint(cantidad): return [0 for i in range(cantidad)]

Y así para cada tipo que necesite...

Los defectos de esa solución son obvios. Una mejor solución:

def listadecosas(tipo, cantidad): return [tipo() for i in range(cantidad)]

Esa es una aplicación de programación genérica. Estamos creando código que solo puede tener un efecto cuando, más

adelante, lo apliquemos a un tipo. Es un caso extremo de lo mostrado anteriormente, en este caso literalmente el tipo

a usar no importa. ¡Cualquier tipo que se pueda instanciar sin argumentos sirve!

Desde ya que es posible – como diría un programador C++ – “especializar el template”:

def templatelistadecosas(tipo): def listadecosas(cantidad): return [tipo() for i in range(cantidad)] return listadecosas

>>> listadestr=templatelistadecosas(str) >>> listadeint=templatelistadecosas(int) >>> >>> listadestr(10) ['', '', '', '', '', '', '', '', '', ''] >>> listadeint(10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

El truco de ese fragmento es que templatelistadecosas crea y devuelve una nueva función cada vez que la

invoco con un tipo específico. Esa función es la “especialización” de templatelistadecosas.

Otra forma de hacer lo mismo es utilizar la función functools.partial de la biblioteca standard:

1.5. Acerca del Autor 15

import functools def listadecosas(tipo, cantidad): return [tipo() for i in range(cantidad)]

listadestr=functools.partial(listadecosas, (str)) listadeint=functools.partial(listadecosas, (int))

Este enfoque para resolver el problema es más típico de la así llamada “programación funcional”, y partial es

una función de orden superior (higher-order function) que es una manera de decir que es una función que se aplica a

funciones.

¿Notaron que todo lo que estamos haciendo es crear funciones muy poco específicas?

Por ejemplo, listadecosas también puede hacer esto:

import random >>> listaderandom=functools.partial(listadecosas, ( lambda : random.randint(0,100))) >>> listaderandom(10) [68, 92, 83, 55, 89, 2, 9, 74, 9, 58]

Después de todo... ¿Quién dijo que tipo era un tipo de datos? ¡Todo lo que hago con tipo es tipo()!

O sea que tipo puede ser una clase, o una función, o cualquiera de las cosas que en python se llaman callables.

lambdas

lambda define una “función anónima”. EL ejemplo usado es el equivalente de

def f(): return random.randint(0,100) listaderandom=functools.partial(listadecosas, f)

La ventaja de utilizar lambda es que, si no se necesita reusar la función, mantiene la definición en el lugar donde se

usa y evita tener que buscarlo en otra parte al leer el código.

Más información

Decoradores

En un capítulo posterior vamos a ver fragmentos de código como este:

Esos misteriosos @algo son decoradores. Un decorador es simplemente una cosa que se llama pasando la función a

decorar como argumento. Lo que en matemática se denomina “composición de funciones”.

Usados con cuidado, los decoradores mejoran mucho la legibilidad de forma casi mágica. ¿Querés un ejemplo? Así se

vería ese código sin decoradores:

def alta(): """Crea un nuevo slug""" : :

UGH

alta = bottle.route('/')(bottle.view('usuario.tpl')(alta))

¿Cuándo usar decoradores? Cuando querés cambiar el comportamiento de una función, y el cambio es:

16 Capítulo 1. Introducción