Effektiver Python-Hinweis Punkt 15 Wissen, wie sich Schließungen auf den Funktionsumfang beziehen

Es ist ein Memo-Schreiben des Buches effektive Python von O'Reilly Japan. https://www.oreilly.co.jp/books/9784873117560/ P31~35

Wenn Sie den Umfang des Abschlusses kennen, können Sie schönen Code schreiben.

** Sortierbeispiel ** Sortieren Sie die Zahlen der Reihe nach, aber nehmen Sie an, Sie haben eine Zahl, die Sie priorisieren möchten

def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
        return (1, x)
    values.sort(key=helper)

numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sort_priority(numbers, group)
print(numbers)

>>>
[2, 3, 5, 7, 1, 4, 6, 8]

Wenn Sie das Konzept der Schließung nicht kennen, können Sie sich kaum vorstellen, wie es funktioniert. Hier gibt es drei Punkte

  1. Der Schließungsmechanismus ermöglicht der Hilfsfunktion den Zugriff auf die Gruppe, die das Argument der Funktion sort_priority ist.
  2. Da die Python-Funktion ein erstklassiges Objekt ist, kann die Hilfsfunktion als Schlüsselargument der Sortiermethode zugewiesen werden.
  3. Die Prioritätsreihenfolge wird getrennt, indem der erste Index durch das Taple, das den Rückgabewert der Hilfsfunktion darstellt, in 0 und 1 getrennt wird.

** Bestimmen Sie, ob es in der Prioritätenliste enthalten ist oder nicht ** Basierend auf dem obigen Code möchte ich eine Implementierung implementieren, die True zurückgibt, wenn sie in der Prioritätsliste enthalten ist.

def sort_priority2(numbers, group):
    found = False
    def helper(x):
        if x in group:
            found = True #Es sollte hier wahr sein. .. ..
            return(0, x)
        return(1, x)
    numbers.sort(key=helper)
    return found

found = sort_priority2(numbers, group)
print('Found', found)
print(numbers)

>>>

Found False
[2, 3, 5, 7, 1, 4, 6, 8]

Ursprünglich sollte Found in der Berechnung True sein, aber aus irgendeinem Grund wird False zurückgegeben. Der Grund dafür ist der ** Umfang ** der Schließung.

Wenn Sie den Umfang nicht verstehen, leiden Sie unter mysteriösem Verhalten

Der obige Code gibt nicht False zurück, da der Bereich von Found außerhalb der Hilfsfunktion bleibt. Mit anderen Worten

def sort_priority2(numbers, group):
    found = False        #Weil gefunden im Umfang hier existiert. ..
    def helper(x):
        if x in group:
            found = True #Gehen Sie hier nicht zum Bereich
            return(0, x)
        return(1, x)
    numbers.sort(key=helper)
    return found

Infolgedessen wird False zurückgegeben, das einen Bereich höher ist. Um dies zu vermeiden, bietet Python3 eine ** nichtlokale ** Funktion. Nicht lokal drückt das Zielfernrohr aus dem Verschluss


def sort_priority3(numbers, group):
    found = False
    def helper(x):
        nonlocal found #Hier liegt der Umfang der gefundenen außerhalb der Hilfsfunktion
        if x in group:
            found =True
            return(0, x)
        return(1, x)
    numbers.sort(key=helper)
    return found

found = sort_priority3(numbers, group)
print('Found', found)
print(numbers)

>>>

Found True
[2, 3, 5, 7, 1, 4, 6, 8]

Dies ist die beabsichtigte Bewegung.

Wenn Sie jedoch nicht lokal in einer Großfunktion verwenden, wirkt sich dies auf den Bereich unbeabsichtigter Teile aus. Seien Sie also vorsichtig. Wenn Sie auf der sicheren Seite sein möchten, ist es besser, es in eine ähnliche Klasse zu verpacken, anstatt in die nichtlokale Funktion.

class Sorter(object):
    def __init__(self, group):
        self.group = group
        self.found = False
        
    def __call__(self, x):
        if x in self.group:
            self.found = True
            return(0, x)
        return(1, x)

sorter = Sorter(group)
numbers.sort(key=sorter)
assert sorter.found is True

>>>
(Keine Ausnahme wegen Behauptung)

Dieser kann verwendet werden, ohne sich um den Umfang zu kümmern.

Übrigens wird nonlocal in python2 nicht unterstützt.

Fazit

  1. Wenn Sie den Umfang des Abschlusses kennen, können Sie präzisen Code schreiben
  2. Unbeabsichtigtes Verhalten tritt auf, wenn Sie den Bereichsbereich nicht verstehen
  3. python3 kann durch nichtlokale Verwendung außerhalb des Verschlusses erweitert werden (es ist jedoch besser, es auf einfache Funktionen zu beschränken).

Recommended Posts

Effektiver Python-Hinweis Punkt 15 Wissen, wie sich Schließungen auf den Funktionsumfang beziehen
Verwendung der Zip-Funktion von Python
[Python] Verwendung von Hash-Funktion und Taple.
EP 15 Know How Closures interagieren mit variablem Umfang
So installieren Sie Python
[Einführung in Python] Wie iteriere ich mit der Bereichsfunktion?
Wie Sie das aktuelle Verzeichnis in Python in Blender kennen
So installieren Sie Python
Beachten Sie, dass Python ein Daemon ist
Führen Sie die Python-Funktion von Powershell aus (wie Sie Argumente übergeben).
Effektives Python-Memo Punkt 3
[Python] So rufen Sie eine Funktion von c aus Python auf (ctypes edition)
So verschieben Sie ein zweidimensionales Array nur mit Python [Hinweis]
Effektives Python-Memo-Element 19 Geben Sie Schlüsselwortargumenten optionales Verhalten
Wie man aus einer Wahrscheinlichkeitsdichtefunktion in Python tastet
Ich wusste nicht, wie ich die [Python] für die Anweisung verwenden sollte
Effektiver Python-Hinweis Punkt 16 Erwägen Sie, einen Generator zurückzugeben, ohne eine Liste zurückzugeben
[Einführung in Python] So erhalten Sie Daten mit der Funktion listdir
[Neueste Version 2020.8] So installieren Sie Python
So installieren Sie Python [Windows]
python3: Verwendung der Flasche (2)
[Python] Verwendung von Liste 1
So rufen Sie eine Funktion auf
So aktualisieren Sie Pythons Tkinter auf 8.6
Wie benutzt man Python Argparse?
[Hinweis] Verwendung von virtualenv
Python: Wie man pydub benutzt
[Python] Verwendung von checkio
So führen Sie Notepad ++ Python aus
So ändern Sie die Python-Version
Wie man in Python entwickelt
[Python] Wie man Skalar beurteilt
[Python] Verwendung von input ()
Wie benutzt man Python Lambda?
[Python] Verwendung von virtualenv
python3: Verwendung der Flasche (3)
python3: Wie man eine Flasche benutzt
Verwendung von Python-Bytes
Effektives Python-Memo Element 11 Verwenden Sie zip, um Iteratoren parallel zu verarbeiten
Wie Sie die interne Struktur eines Objekts in Python kennen
[Einführung in Python] So teilen Sie eine Zeichenfolge mit der Funktion split
[Python 3.8 ~] Wie man rekursive Funktionen mit Lambda-Ausdrücken intelligent definiert
Effektiver Python-Hinweis Punkt 17 Respektieren Sie die Sicherheit, wenn Sie Iteratoren für Argumente verwenden
Grundlegende Grammatik des Python3-Systems (Verwendung von Funktionen, Schließung, Lambda-Funktion)
[Python] Erklärt anhand eines Beispiels, wie die Formatierungsfunktion verwendet wird
So installieren Sie Python mit Anaconda
[Python] Wie man MP3-Daten fFT
[Python] Wie man PCA mit Python macht
Python: So verwenden Sie Async mit
Verwendung der Zip-Funktion
EP5 Know How zum Schneiden von Sequenzen
[Python] Wie man nCk ableitet (ABC156-D)
[Python] Verwendung der Pandas-Serie
So sammeln Sie Bilder in Python
Verwendung von Anfragen (Python Library)
Verwendung von SQLite in Python
[Einführung in Python] So analysieren Sie JSON
So erhalten Sie die Python-Version
So erstellen Sie eine rekursive Funktion
Erste Schritte mit Python