Esta es la décima colección de consejos y programación de Python de mi feed @pythonetc.
Selecciones anteriores0_0
0_0
es una expresión completamente correcta en Python.
Ordenar lista con Ninguno
Ordenar una lista con valores
None
puede ser una tarea desalentadora:
In [1]: data = [ ...: dict(a=1), ...: None, ...: dict(a=-3), ...: dict(a=2), ...: None, ...: ] In [2]: sorted(data, key=lambda x: x['a']) ... TypeError: 'NoneType' object is not subscriptable
Puede intentar eliminar todos los Ninguno y devolverlos después de ordenarlos (al principio o al final de la lista, según la tarea):
In [3]: sorted( ...: (d for d in data if d is not None), ...: key=lambda x: x['a'] ...: ) + [ ...: d for d in data if d is None ...: ] Out[3]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
Pero es inconveniente. Mejor use una
key
más compleja:
In [4]: sorted(data, key=lambda x: float('inf') if x is None else x['a']) Out[4]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
Si estamos hablando de tipos para los que el infinito es inaceptable, puede ordenar las tuplas:
In [5]: sorted(data, key=lambda x: (1, None) if x is None else (0, x['a'])) Out[5]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
Llamar random.seed ()
Cuando bifurcas el proceso, la semilla aleatoria que utilizas se copiará a todos los procesos resultantes. Como resultado, se puede generar el mismo resultado "aleatorio" en ellos.
Para evitar esto, debe llamar manualmente
random.seed()
en cada proceso. Pero si usa el módulo de
multiprocessing
, lo hará por usted.
Por ejemplo:
import multiprocessing import random import os import sys def test(a): print(random.choice(a), end=' ') a = [1, 2, 3, 4, 5] for _ in range(5): test(a) print() for _ in range(5): p = multiprocessing.Process( target=test, args=(a,) ) p.start() p.join() print() for _ in range(5): pid = os.fork() if pid == 0: test(a) sys.exit() else: os.wait() print()
Obtén algo como esto:
4 4 4 5 5 1 4 1 3 3 2 2 2 2 2
Además, si usa Python 3.7 y superior, entonces gracias al nuevo at_fork
at_fork
puede hacer
lo mismo con
os.fork
.
El código Python 3.7 anterior da este resultado:
1 2 2 1 5 4 4 4 5 5 2 4 1 3 1
Además de 0
A primera vista parece que la
sum([a, b, c])
equivalente a
a + b + c
, aunque en realidad el equivalente sería
0 + a + b + c
. Por lo tanto, esta expresión no puede funcionar con tipos que no admiten la adición a
0
:
class MyInt: def __init__(self, value): self.value = value def __add__(self, other): return type(self)(self.value + other.value) def __radd__(self, other): return self + other def __repr__(self): class_name = type(self).__name__ return f'{class_name}({self.value})' In : sum([MyInt(1), MyInt(2)]) ... AttributeError: 'int' object has no attribute 'value'
Para solucionar esto, puede proporcionar un elemento de inicio personalizado que se utilizará en lugar de
0
:
In : sum([MyInt(1), MyInt(2)], MyInt(0)) Out: MyInt(3)
sum
diseñado para agregar tipos
float
e
int
, aunque puede funcionar con cualquier otro tipo personalizado. Sin embargo, se niega a agregar
bytes
,
bytearray
y
str
, ya que
join
para este propósito:
In : sum(['a', 'b'], '') ... TypeError: sum() can't sum strings [use ''.join(seq) instead] In : ints = [x for x in range(10_000)] In : my_ints = [Int(x) for x in ints] In : %timeit sum(ints) 68.3 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) In : %timeit sum(my_ints, Int(0)) 5.81 ms ± 20.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Finalización del índice en Jupyter Notebook
Usando el método
_ipython_key_completions_
, puede personalizar la finalización del índice en un Jupyter Notebook. De esta manera puede controlar lo que se muestra en la pantalla si presiona Tab después de algo como
d["x
:

Tenga en cuenta que el método no recibe la cadena a buscar como argumento.