@Pythonetc Junio ​​2019


Esta es la undécima selección de consejos y programación de Python de mi feed @pythonetc.

Colecciones anteriores


El 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 

Source: https://habr.com/ru/post/458686/


All Articles