Publicado el 8 de Mayo del 2017
1.606 visualizaciones desde el 8 de Mayo del 2017
1,1 MB
40 paginas
Creado hace 12a (11/09/2012)
Python
3000
Facundo Batista
Gracias especiales a nessita por su indispensable ayuda con LaTEXpara esta presentación
¿Python queloqué?
Evolución normal
I Versiones: Python x.y.z
I x: mayor
I y: menor
I z: bugfix
I Normalmente no rompemos (casi) nada
I warnings
I from future
I Se barajaba una versión disruptiva desde hace años
I El futuro ya llegó
¿Por qué? ¿Para qué?
I Corregir errores de diseño, viejos principalmente
I clases clásicas
I división de enteros
I print como declaración
I Los tiempos cambian: compromiso espacio/velocidad
I str / unicode
I int / long
I Nuevos paradigmas
I views de los diccionarios
I anotaciones en los argumentos
Nuevas
funcionalidades
y mejoras
Textos, textos, textos!
I En Py2: cadenas normales y unicode
I no estaban bien separados los conceptos
I confundía, sorprendía
I En Py3 tenemos bytes y texto
I texto: nos abstraemos de la codificación
I bytes: una secuencia de valores de 8 bits
I son dos tipos de datos totalmente separados
Textos en Python 3
I Distinguimos ambos literales
I b’...’: bytes
I ’...’: cadenas de caracteres (unicode)
I u’...’: también caracteres, por compatibilidad
I No hay conversiones implícitas
I menos confusión, menos sorpresas
I más fácil de seguir la Regla de Oro de Unicode
I Las fuentes tiene un default: UTF-8
I menos confusión, menos sorpresas
I no necesitamos más el -*- coding:... -*-
I open() tiene ’encoding’ opcional!
I como codecs.open()
I Unicode en los nombres
I >>> año = 3000
Avistando diccionarios
I dict.keys(), .values(), .items(), ahora devuelven una vista
I Se actualizan cuando el diccionario cambia
>>> d = dict(a=3, b=4)
>>> v = d.values()
>>> v
dict_values([3, 4])
>>> list(v)
[3, 4]
>>> d["c"] = 8
>>> list(v)
[3, 8, 4]
I Son re-iterables, no se gastan como el viejo .iteritem()
>>> list(v)
[3, 8, 4]
>>> list(v)
[3, 8, 4]
Asterisquémonos
I Podemos tener argumentos sólo nombrados
print(args , bar)
>>> def foo(*args , bar=None):
...
>>> foo(1)
(1,) None
>>> foo(1, 2)
(1, 2) None
>>> foo(1, bar=7)
(1,) 7
I Asignación múltiple de largo variable
>>> a, b, *c = range(5)
>>> a, b, c
(0, 1, [2, 3, 4])
>>> a, *b, c = range(5)
>>> a, b, c
(0, [1, 2, 3], 4)
La función format()
I Integrada, formatea un sólo valor
>>> format(1.2321 , "8.2f")
'
1.23'
I Cómo método de las cadenas
>>> "Son {0}: {val:.2f}".format("pesos", val=4)
'Son pesos: 4.00'
I Más poder, más flexibilidad
I trabaja bien con los códigos de formateo conocidos
I se puede definir el comportamiento del formato: __format__
>>> "{:,.2f}".format(Decimal(3123.5))
'3,123.50'
Abstract Base Classes (ABC)
I Nos permite definir clases abstractas con las cuales cumplir
I El módulo collections define estrictamente comportamientos
>>> dir(collections)
[ ... , 'Callable', 'Container', 'Hashable',
'Iterable', 'Sequence', ... ]
I El chequeo rígido de interfaces es nuevo a Python
I quizás dispare nuevas metodologías
I con suerte no hará que aparezcan miles de controles isinstance()
I el tiempo dirá si ayudan o lastiman al duck typing
Más y mejores números I
I Literales binarios y la función bin()
>>> 0b1001
9
>>> bin(34)
'0b100010'
I ¿Cuantos bits usa para un número?
>>> (27).bit_length()
5
I Fracciones!
>>> Fraction(1, 3)
Fraction(1, 3)
>>> print(Fraction(1, 3))
1/3
>>> print(Fraction(1, 3) * 3)
1
Más y mejores números II
I Nueva forma de buscar la representación más exacta de un float
I 1.1 es 1.100000000000000088817841970012523233890533447265625
I antes se tomaban 17 decimales y ya: '1.1000000000000001'
I ahora se busca el número más corto que siga siendo igual a lo
almacenado: '1.1'
I igual, lo subyacente no cambia
>>> 1.1 + 2.2 == 3.3
False
I Mejoras en Decimal
I Conversión exacta desde float
>>> Decimal.from_float(1.1)
Decimal('1.100000000000000088878 ... 0533447265625')
I Está codeada (también) en C: de 12 a 120 veces más rápida
Interactuando con el sistema
I La E/S no depende más de <stdio.h> de C
I independiente de la plataforma
I unicode bien integrada en el stack subyacente
I reescrito en C en 3.1, en 3.0 estaba en Python y era lento
I nuevo flag ’x’ para abrir un archivo: exclusivamente un archivo nuevo
I os.sendfile() provee ’zero-copy’ entre archivos o sockets
I Todas las excepciones contra el sistema son OSError
I Deprecamos IOError, EnvironmentError, WindowsError,
mmap.error, etc...
I No hace falta revisar el errno para saber qué pasó, hay excepciones
puntuales como FileNotFoundError, NotADirectoryError,
PermissionError, TimeoutError, etc...
Ejecuciones simultáneas
I Nuevo paquete futures para ejecutar código ’en paralelo’
PRIMES = [ lista de nros ]
def is_prime(n):
(código para averiguar si n es primo)
with concurrent.futures.ProcessPoolExecutor() as executor:
all_calls = executor.map(is_prime , PRIMES)
for number , prime in zip(PRIMES , all_calls):
print(' %d is prime: %s' % (number , prime))
I Procesos (sensible cantidad default) o hilos
Mejoras en la sintaxis I
I Decoradores de clase
I Fácil de aprender
I Mucho más sencillo que metaclases
cls.log = lambda self , *a, **k: print(a, k)
return cls
>>> def f(cls):
...
...
...
>>> @f
... class C():
...
...
>>> c = C()
>>> c.log(2)
(2,) {}
pass
I Atrapando excepciones con menos riesgo
I except KeyError, err: → except KeyError as err:
I menos confuso: except KeyError, AttributeError:
Mejoras en la sintaxis II
I Declaración nonlocal
nonlocal b
b = 1
>>> b = 5
>>> def f():
b = 3
...
...
def g():
...
...
...
...
...
>>> f()
1
>>> print(b)
5
g()
print(b)
I Anotación de funciones
I def promedios(valores: list) -> float:
I se permite cualquier expresión
I el intérprete no le da significado o propósito
Mejoras en la sintaxis III
I Literales para set, y set comprehensions
>>> {1, 2, 2, 3}
{1, 2, 3}
>>> {x**2 for x in (-1, 0, 1)}
{0, 1}
I También dict comprehensions!
>>> {y:x for x,y in d.items()}
{0: 'a', 1: 'b', 2: 'c'}
I Abriendo muchos archivos con with
>>> with open('mylog') as inp_f , open('out', 'w') as out_f:
...
...
...
if '<critical >' in line:
for line in inp_f:
out_f.write(line)
Más y mejores módulos
I Diccionarios ordenados
I collections.OrderedDict()
I Buenísimo para representar configuración
I Cache automático para funciones:
I @functools.lru_cache(maxsize=300)
I para pagar el costo una vez en funciones caras
I Acumulador
>>> list(itertools.accumulate([8, 2, 50]))
[8, 10, 60]
I muy usado al integrar, o trabajando con probabilidady y estadística
I Y muchos más
I argparse, para interpretar lineas de comandos, más completo y fácil
I faulthandler, para crashes como un Segmentation Fault
I lzma, soporte para .xz y .lzma en la biblioteca estándar!
I Entornos virtuales, como virtualenv
Otras mejoras que no lastiman a nadie I
I Bytes mutables: bytearray
>>> bytearray(5)
bytearray(b'\x00\x00\x00\x00\x00')
>>> b = bytearray(range(5))
>>> b
bytearray(b'\x00\x01\x02\x03\x04')
>>> b[3] = 255
>>> b
bytearray(b'\x00\x01\x02\xff\x04')
I Entregando desde otro lado
>>> def g(x):
for i in range(x):
yield i
>>> def f(x):
yield from range(x)
>>> list(g(5)), list(f(5))
[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]
Otras mejoras que no lastiman a nadie II
I Nombres completos para clases y funciones
def meth(self):
pass
class D:
>>> class C:
...
...
...
...
>>> C.D.__name__
'D'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__name__
'meth'
>>> C.D.meth.__qualname__
'C.D.meth'
I No necesitamos argumentos para super()
Muchas mejoras
no son
compatibles
print es ahora una función
I El cambio es sencillo
I print 'pyar' → print('pyar')
I Flexibilidad
I fácil de reemplazar por tu propia función
I más opciones, mejor legibilidad
I print(m, file=stderr)
I print('\r' % avance, end='', flush=True)
Iteradores/generadores FTW!
I La idea es tratar de usar siempre iteradores o generadores
I Es mucho más eficiente en velocidad y memoria
I Sólo es molesto en el intérprete interactivo
I Muchos cambios para ir hacia esto
I range() ahora se comporta como xrange() (que no está más)
I map() y filter()
I dict.items(), .keys(), .values()
I no están más dict.iteritems(), dict.iterkeys(), etc.
I muchos son tipos de datos específicos, no realmente iteradores
I Tenemos un next(it) integrado
I .next() → .__next__()
Ordenando ideas
I Chau al orden universal
I no hay más comparaciones arbitrarias
I [2, 'w'].sort() → TypeError
I sorted() y list.sort() no tienen más cmp
I usar key
I más limpio, más fácil
I acordarse que el sort es estable!
>>> seq = [('b', 2), ('a', 2), ('b', 1), ('c', 1)]
>>> seq.sort(key=itemgetter(1))
>>> seq.sort(key=itemgetter(0))
>>> seq
[('a', 2), ('b', 1), ('b', 2), ('c', 1)]
I tampoco tenemos al cmp integrado
Pasamos la escoba
I Eliminamos <>
I Usar !=
I Eliminamos d.has_key(x)
I Usar x in d
I Eliminamos reload()
I Usar imp.reload()
I Eliminamos reduce()
I Usar functools.reduce()
I Eliminamos apply()
I Usar f(*args)
I Eliminamos basestring
I No tenemos más bytes y caracteres mezclados!
I Eliminamos los ``
I Usar repr()
Excepciones también como nuevas
I raise 'foo' → TypeError
I La sintaxis del raise es
I raise Exception(args)
I raise Exception(args) from traceback
I La sintaxis del except es
I except Exception:
I except Exception1, Exception2:
I except Exception as var:
Seguimos cambiando I
I No más clases clásicas
I Todas son nuevas
I Cambió la sintáxis para indicar metaclases
>>> class C(metaclass= ... ):
I Enteros y no tanto
I Los int y long ahora son el mismo objeto
I División verdadera: 1/2 devuelve 0.5
I Nuevos literales para otras bases
>>> 0x101
257
>>> 0o101
65
>>> 0b101
5
Seguimos cambiando II
I Una biblioteca con menos polvo
I Se eliminaron módulos viejos no mantenidos
I Se armó un nivel más, es más intuitiva
I El import relativo ahora es explícito
I import foo no es más dentro del paquete
I from .foo import bar
I None, True y False ahora son palabras reservadas
I True = 0 → SyntaxError
I No tenemos más el desempaquetado de tuplas en los parámetros
I def f(a, (b, c)): → SyntaxErro
Comentarios de: Python 3000 (0)
No hay comentarios