[Python-Tricks] 5 kleine, aber nützliche Python-Tricks

Ich möchte eine Python-Codierungstechnik vorstellen, die ich nicht viel gesehen habe. Es tut mir leid, wenn es unerwartet groß ist. Ich möchte so viel Beispielcode wie möglich einfügen, um zu zeigen, wie es tatsächlich funktioniert. Da es Nischentechnologien zusammenfasst, wird davon ausgegangen, dass Sie Python in gewissem Umfang schreiben können.

functools.partial Sie können dies verwenden, um ** eine Funktion mit festen Argumenten ** für eine Funktion zu erstellen. Ich denke, es ist schneller, sich den Code anzusehen.

import functools

def add(x, y):
    return x + y

add_fixed_y = functools.partial(add, y=5)
print(add_fixed_y(2)) # 7

Ich weiß nicht, wofür dies allein nützlich sein wird, daher möchte ich meine eigene Verwendung vorstellen. Ich benutze es für die ** open Funktion ** der Datei.

open_utf_8 = functools.partial(open, encoding="utf-8")
r_open_utf_8 = functools.partial(open_utf_8, mode="r")
w_open_utf_8 = functools.partial(open_utf_8, mode="w")

with w_open_utf_8("something_great.txt") as wf:
    wf.write("Hello World!")

Auf diese Weise können Sie die Konstanten innerhalb des Codes reduzieren und den Tippfehler im Codierungsteil verhindern.

next und Generator

Die Ausdrücke in der Listeneinschlussnotation können für Generatorausdrücke verwendet werden, und das Erstellen von Generatorobjekten wurde in anderen Artikeln eingeführt.

gen = (i ** 2 for i in range(10))
print(gen) # <generator object <genexpr> at 0x~~>

Wie ist dies bei der eigentlichen Codierung nützlich? Ich benutze es, um den ersten Index ** zu finden, der die ** Kriterien erfüllt. Es wird zum ** Runden der Zeichenfolge auf die angegebene Anzahl von Bytes oder weniger ** verwendet.

from itertools import accumulate

def str_clamp_bytes(value: str, max_bytes: int) -> str:
    byte_count = (len(s.encode("utf-8")) for s in value)
    try:
        end_slice = next(i for i, v in enumerate(accumulate(byte_count)) if v > max_bytes)
    except StopIteration:
        return value
    return value[:end_slice]

(i für i, v in enumerate (akkumulieren (byte_count)) wenn v> max_bytes) ist der Generator und wenn v> max_bytes der bedingte Ausdruck ist. end_slice wird der erste Index zugewiesen, der v> max_bytes erfüllt. Wenn es keinen Index gibt, der die Bedingungen erfüllt, tritt eine StopIteration-Ausnahme auf. Fangen Sie ihn also ab und geben Sie die ursprüngliche Zeichenfolge zurück. Der Generator ist ausreichend, da "byte_count" nur für "akkumulieren" verwendet wird.

Globale Variable __debug__

Diese Variable wird zu "False", wenn beim Start die Option "-O" (nicht Null) hinzugefügt wird. Wenn Sie die Option "-O" hinzufügen, wird die Anweisung "assert" ungültig und Sie können das Programm beschleunigen, sodass Sie es problemlos in der Produktversion hinzufügen können. Ich benutze es für den Prozess der ** Lieferung nur der Produktversion **.

def broadcast_debug():
    pass

def broadcast_prod():
    pass

(broadcast_debug if __debug__ else broadcast_prod)()

lru_cache Dekorateur

Wenn Sie sich das Funktionsargument / Rückgabewert-Paar im Wörterbuch merken, gibt das zuvor übergebene Argument den vorherigen Rückgabewert ohne Verarbeitung zurück.

from functools import lru_cache

@lru_cache
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(10))

Da es sich um ein Wörterbuch handelt, ist die Zugriffsgeschwindigkeit schlechter als beim reinen Schreiben von Memos, aber die Benutzerfreundlichkeit ist großartig. Danach kann es auch dann behandelt werden, wenn ** Zeichenfolgen usw. als Argumente ** verwendet werden, die durch die Memokonvertierung nicht behandelt werden können.

inspect.getmembers Sie können ** alle Mitglieder aus dem Modul holen **. Sie können den Elementtyp mit dem zweiten Argument angeben.

import inspect
import copy

print(inspect.getmembers(copy, inspect.isclass))
# >> [('Error', <class 'copy.Error'>), ('error', <class 'copy.Error'>)]

** Sie können alle Klassen aus dem Modul extrahieren **, sodass Sie sie alle auf einmal abrufen können, ohne den Aufwand von "load_classes = [class_A, class_B, ...]". Und Sie müssen nicht vergessen, es hinzuzufügen. Das Klassenobjekt hat ein "bases" -Mitglied, und alle geerbten Klassenobjekte sind als Tapples enthalten. Ich denke, Sie können diesen Bereich zum Filtern verwenden.

Schließlich

Ich habe einen Trick eingeführt, den ich für "praktisch, aber ich sehe nicht viel" halte. Bitte lassen Sie mich wissen, wenn Sie Fehler oder Tippfehler haben.

Recommended Posts

[Python-Tricks] 5 kleine, aber nützliche Python-Tricks
[Python] Super nützliches Debugging
3 Jupyter Notebook (Python) Tricks
Python nützliche Memo-Links
Python ist schmerzhaft. Aber benutze
Nützliche Tricks in Bezug auf Listen und Anweisungen in Python
Installieren Sie Python 3.7 Anaconda auf dem MAC, aber Python 2
Python aber einfache Visualisierung mit PixieDust