Esta es la undécima selección de consejos y programación de Python de mi feed @pythonetc.
←
Colecciones anterioresEl carácter
\
en una línea regular tiene un significado especial.
\t
es un carácter de tabulación,
\r
es un salto de línea, etc.
Para deshabilitar este comportamiento, puede usar cadenas sin formato. Entonces
r'\t'
se convertirá en solo una barra invertida
t
.
Obviamente, no puedes usar
'
inside
r'...'
. Y aunque esta restricción se puede eludir con
\
, sin embargo, la línea
\
seguirá siendo:
>>> print(r'It\'s insane!') It\'s insane!
Los generadores de listas pueden contener más de un par de expresiones
for
y
if
:
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 definidas previamente:
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) ]
Puede mezclar
if
y
for
lo que desee:
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 especificar métodos de ordenación personalizados. Esto se hace utilizando el argumento
key
, que describe cómo convertir los valores originales para una comparación posterior:
>>> 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 trabajan con comparación admiten el argumento
key
. De los que se rumorea, se pueden mencionar
heapq
(soporte parcial) y
bisect
(sin soporte).
Hay dos maneras de ir en esta situación. Puede 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 necesite crear varias versiones de tales clases, porque los objetos se pueden comparar de diferentes maneras. Esto puede ser inconveniente, por lo que hay una segunda forma.
En lugar de crear objetos personalizados, puede usar tuplas
(a, b)
, en las que
a
es el valor para comparar (prioridad)
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 y el generador de funciones 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
Esto significa que para crear un generador vacío, necesita hacer esto:
In : def g(): ...: if False: ...: yield ...: In : list(g()) Out: []
Pero dado que el
yield from
admite iteradores simples, es decir, una versión más agradable:
def g(): yield from []
En Python, puede crear cadenas de operadores de comparación:
>>> 0 < 1 < 2 True >>> 0 < 1 < 0 False
Dichas cadenas no tienen que ser matemáticamente correctas, puede mezclar
>
y
<
:
>>> 0 < 1 > 2 False >>> 0 < 1 < 2 > 1 > 0 True
==
operadores también son compatibles.
is
y
in
:
>>> [] is not 3 in [1, 2, 3] True
Cada operador se aplica a dos operandos adyacentes.
a OP1 b OP2 c
estrictamente equivalente a
(a OP1 b) AND (b OP2 c)
. No se realiza la comparación de
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)
Resultado:
1 < 2 2 <= 3 3 == 3 True