Es una nueva selección de consejos y trucos sobre Python y la programación de mi canal de Telegram @pythonetc.
←
Publicaciones anterioresEl símbolo
\
en una cadena regular tiene un significado especial.
\t
es el carácter de tabulación,
\r
es el retorno de carro, etc.
Puede usar cadenas sin formato para deshabilitar este comportamiento.
r'\t'
es solo barra invertida
t
.
Obviamente no puedes usar
'
inside
r'...'
. Sin embargo, todavía puede ser escapado por
\
, pero
\
se conserva en la cadena:
>>> print(r'It\'s insane!') It\'s insane!
Las comprensiones de listas pueden contener más de una
for
y
if
cláusulas:
In : [(x, y) for x in range(3) for y in range(3)] Out: [ (0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2) ] In : [ (x, y) for x in range(3) for y in range(3) if x != 0 if y != 0 ] Out: [(1, 1), (1, 2), (2, 1), (2, 2)]
Además, cualquier expresión dentro de
for
y
if
puede usar todas las variables que se definieron antes:
In : [ (x, y) for x in range(3) for y in range(x + 2) if x != y ] Out: [ (0, 1), (1, 0), (1, 2), (2, 0), (2, 1), (2, 3) ]
Puedes mezclar
if
s y
for
s como quieras:
In : [ (x, y) for x in range(5) if x % 2 for y in range(x + 2) if x != y ] Out: [ (1, 0), (1, 2), (3, 0), (3, 1), (3, 2), (3, 4) ]
La función
sorted
permite proporcionar un método personalizado para ordenar. Se realiza con el argumento
key
, que describe cómo convertir los valores originales en valores que realmente se comparan:
>>> x = [dict(name='Vadim', age=29), dict(name='Alex', age=4)] >>> sorted(x, key=lambda v: v['age']) [{'age': 4, 'name': 'Alex'}, {'age': 29, 'name': 'Vadim'}]
Por desgracia, no todas las bibliotecas que funcionan con comparación admiten algo como este argumento
key
. Ejemplos notables son
heapq
(soporte parcial) y
bisect
(sin soporte).
Hay dos formas de lidiar con la situación. El primero es usar objetos personalizados que admitan una comparación adecuada:
>>> class User: ... def __init__(self, name, age): ... self.name = name ... self.age = age ... def __lt__(self, other): ... return self.age < other.age ... >>> x = [User('Vadim', 29), User('Alex', 4)] >>> [x.name for x in sorted(x)] ['Alex', 'Vadim']
Sin embargo, es posible que deba crear varias versiones de tales clases, ya que hay más de una forma de comparar objetos. Puede ser agotador, pero puede resolverse fácilmente por la segunda vía.
En lugar de crear objetos personalizados, puede usar tuplas
(a, b)
donde
a
es el valor para comparar (también conocido como prioirty)
b
es el valor original:
>>> users = [dict(name='Vadim', age=29), dict(name='Alex', age=4)] >>> to_sort = [(u['age'], u) for u in users] >>> [x[1]['name'] for x in sorted(to_sort)] ['Alex', 'Vadim']
La diferencia entre la definición de la función y la definición del generador es la presencia de la palabra clave de
yield
en el cuerpo de la función:
In : def f(): ...: pass ...: In : def g(): ...: yield ...: In : type(f()) Out: NoneType In : type(g()) Out: generator
Eso significa que para crear un generador vacío tienes que hacer algo como esto:
In : def g(): ...: if False: ...: yield ...: In : list(g()) Out: []
Sin embargo, dado que el
yield from
admite iteradores simples, esa versión más atractiva sería esta:
def g(): yield from []
En Python, puede encadenar operadores de comparación:
>>> 0 < 1 < 2 True >>> 0 < 1 < 0 False
Tales cadenas no tienen que ser matemáticamente válidas, puede mezclar
>
y
<
:
>>> 0 < 1 > 2 False >>> 0 < 1 < 2 > 1 > 0 True
También se admiten otros operadores como
==
,
is
y
in
:
>>> [] is not 3 in [1, 2, 3] True
Cada operador se aplica a los dos operandos más cercanos.
a OP1 b OP2 c
es estrictamente igual a
(a OP1 b) AND (b OP2 c)
. No se implica ninguna comparación entre
a
y
c
:
class Spy: def __init__(self, x): self.x = x def __eq__(self, other): print(f'{self.x} == {other.x}') return self.x == other.x def __ne__(self, other): print(f'{self.x} != {other.x}') return self.x != other.x def __lt__(self, other): print(f'{self.x} < {other.x}') return self.x < other.x def __le__(self, other): print(f'{self.x} <= {other.x}') return self.x <= other.x def __gt__(self, other): print(f'{self.x} > {other.x}') return self.x > other.x def __ge__(self, other): print(f'{self.x} >= {other.x}') return self.x >= other.x s1 = Spy(1) s2 = Spy(2) s3 = Spy(3) print(s1 is s1 < s2 <= s3 == s3)
Salida:
1 < 2 2 <= 3 3 == 3 True