Es ist eine neue Auswahl von Tipps und Tricks zu Python und Programmierung von meinem Telegramm-Kanal @pythonetc.
Frühere Veröffentlichungen .
0_0
0_0
ist ein vollständig gültiger Python-Ausdruck.
Sortieren einer Liste mit Keine
Das Sortieren einer Liste mit den Werten
None
kann eine Herausforderung sein:
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
Sie können versuchen, Nones zu entfernen und nach dem Sortieren wieder einzufügen (je nach Aufgabe bis zum Ende oder Anfang der Liste):
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]
Das ist ein Schluck. Die bessere Lösung besteht darin, einen komplexeren
key
:
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]
Für Typen, für die keine Unendlichkeit verfügbar ist, können Sie stattdessen Tupel sortieren:
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]
Random.seed () aufrufen
Wenn Sie Ihren Prozess verzweigen, wird der zufällige Startwert, den Sie verwenden, prozessübergreifend kopiert. Dies kann dazu führen, dass Prozesse das gleiche "zufällige" Ergebnis erzielen.
Um dies zu vermeiden, müssen Sie
random.seed()
in jedem Prozess manuell aufrufen.
Dies ist jedoch nicht der Fall, wenn Sie das
multiprocessing
Modul verwenden, es
erledigt genau das für Sie.
Hier ist ein Beispiel:
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()
Das Ergebnis ist so etwas wie:
4 4 4 5 5 1 4 1 3 3 2 2 2 2 2
Wenn Sie Python 3.7 oder
os.fork
macht os.fork
dank des neuen
at_fork
.
Die Ausgabe des obigen Codes für Python 3.7 lautet:
1 2 2 1 5 4 4 4 5 5 2 4 1 3 1
Hinzufügen zu 0
Es sieht so aus, als ob die
sum([a, b, c])
für
a + b + c
äquivalent ist, während sie tatsächlich
0 + a + b + c
. Das bedeutet, dass es nicht mit Typen funktionieren kann, die das Hinzufügen zu
0
nicht unterstützen:
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'
Um dies zu beheben, können Sie ein benutzerdefiniertes Startelement bereitstellen, das anstelle von
0
:
In : sum([MyInt(1), MyInt(2)], MyInt(0)) Out: MyInt(3)
sum
ist für die Summierung von
float
und
int
Typen gut optimiert, kann jedoch jeden anderen benutzerdefinierten Typ verarbeiten. Es weigert sich jedoch,
bytes
,
bytearray
und
str
zu summieren, da der
join
für diese Operation gut optimiert ist:
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)

Indexvervollständigungen im Jupiter-Notizbuch
Sie können Indexvervollständigungen in Jupyter Notebook anpassen, indem Sie die
_ipython_key_completions_ method
. Auf diese Weise können Sie steuern, was angezeigt wird, wenn Sie nach etwas wie
d["x
:
d["x
Tabulatortaste drücken.

Beachten Sie, dass die Methode die nachgeschlagene Zeichenfolge nicht als Argument erhält.