Ich bin ein Python-Anfänger und habe gerade eine Technik mit Wörterbüchern und Funktionen gelernt. Die Syntax ist einfach und scheint trivial zu sein, aber meine Python-Sinne kribbeln. Etwas sagt mir, dass dies ein tiefgründiges und sehr pythonisches Konzept ist, und ich verstehe seine Bedeutung nicht ganz. Kann jemand dieser Technik einen Namen geben und erklären, wie / warum sie nützlich ist?
Die Technik ist, wenn Sie ein Python-Wörterbuch und eine Funktion haben, die Sie darauf anwenden möchten. Sie fügen ein zusätzliches Element in das Diktat ein, dessen Wert der Name der Funktion ist. Wenn Sie bereit sind, die Funktion aufzurufen, geben Sie den Aufruf indirekt aus, indem Sie sich auf das dict-Element beziehen, nicht auf die Funktion nach Namen.
Das Beispiel, an dem ich arbeite, stammt von Learn Python the Hard Way, 2nd Ed. (Dies ist die Version, die verfügbar ist, wenn Sie sich über Udemy.com anmelden . Leider ist die kostenlose Live-HTML-Version derzeit Ed 3 und enthält dieses Beispiel nicht mehr.)
Umschreiben:
# make a dictionary of US states and major cities
cities = {'San Diego':'CA', 'New York':'NY', 'Detroit':'MI'}
# define a function to use on such a dictionary
def find_city (map, city):
# does something, returns some value
if city in map:
return map[city]
else:
return "Not found"
# then add a final dict element that refers to the function
cities['_found'] = find_city
Dann sind die folgenden Ausdrücke äquivalent. Sie können die Funktion direkt aufrufen oder auf das dict-Element verweisen, dessen Wert die Funktion ist.
>>> find_city (cities, 'New York')
NY
>>> cities['_found'](cities, 'New York')
NY
Kann jemand erklären, um welche Sprachfunktion es sich handelt und wo es beim "echten" Programmieren zu spielen kommt? Diese Spielzeugübung reichte aus, um mir die Syntax beizubringen, brachte mich aber nicht ganz hin.
quelle
Antworten:
Mit einem Diktat können Sie den Schlüssel in einen aufrufbaren übersetzen. Der Schlüssel muss jedoch nicht fest codiert sein, wie in Ihrem Beispiel.
In der Regel handelt es sich hierbei um eine Form der Anruferversendung, bei der Sie den Wert einer Variablen verwenden, um eine Verbindung zu einer Funktion herzustellen. Angenommen, ein Netzwerkprozess sendet Ihnen Befehlscodes. Mit einer Dispatch-Zuordnung können Sie die Befehlscodes einfach in ausführbaren Code übersetzen:
Beachten Sie, dass die Funktion, die wir jetzt aufrufen, vollständig von dem Wert abhängt, von dem der Wert ist
command
. Der Schlüssel muss auch nicht übereinstimmen. Es muss nicht einmal eine Zeichenfolge sein, Sie können alles verwenden, was als Schlüssel verwendet werden kann, und es passt zu Ihrer spezifischen Anwendung.Die Verwendung einer Versandmethode ist sicherer als andere Techniken, wie z. B. die
eval()
Beschränkung der zulässigen Befehle auf das, was Sie zuvor definiert haben.ls)"; DROP TABLE Students; --
Zum Beispiel wird kein Angreifer eine Injektion an einem Dispatch-Tisch vorbeischleichen.quelle
dict
fungiert als Dispatcher (Befehlsmanager, Aufrufer usw.).@Martijn Pieters hat die Technik gut erklärt, aber ich wollte etwas aus Ihrer Frage klären.
Wichtig zu wissen ist, dass Sie NICHT "den Namen der Funktion" im Wörterbuch speichern. Sie speichern einen Verweis auf die Funktion selbst. Sie können dies mit einem
print
auf der Funktion sehen.f
ist nur eine Variable, die auf die von Ihnen definierte Funktion verweist. Mit einem Wörterbuch können Sie ähnliche Dinge gruppieren, es unterscheidet sich jedoch nicht von der Zuweisung einer Funktion zu einer anderen Variablen.Ebenso können Sie eine Funktion als Argument übergeben.
quelle
Beachten Sie, dass die Python-Klasse eigentlich nur ein Syntaxzucker für das Wörterbuch ist. Wenn Sie das tun:
wenn du anrufst
ist wirklich genauso wie:
Das ist nach der Namensauflösung genau das Gleiche wie:
Eine nützliche Technik besteht darin, Benutzereingaben Rückrufen zuzuordnen. Zum Beispiel:
Dies kann alternativ in der Klasse geschrieben werden:
Welche Rückrufsyntax besser ist, hängt von der jeweiligen Anwendung und dem Geschmack des Programmierers ab. Ersteres ist funktionaler, letzteres objektorientierter. Ersteres fühlt sich möglicherweise natürlicher an, wenn Sie die Einträge im Funktionswörterbuch dynamisch ändern müssen (möglicherweise basierend auf Benutzereingaben). Letzteres fühlt sich möglicherweise natürlicher an, wenn Sie über eine Reihe unterschiedlicher Voreinstellungszuordnungen verfügen, die dynamisch ausgewählt werden können.
quelle
5 * x
nach5x
(verzeihen Sie die einfache Analogie).Es gibt zwei Techniken, die mir in den Sinn kommen und auf die Sie sich vielleicht beziehen, von denen keine pythonisch ist, da sie breiter sind als eine Sprache.
1. Die Technik des Versteckens / Einkapselns von Informationen und des Zusammenhalts (normalerweise gehen sie Hand in Hand, sodass ich sie zusammenfasse).
Sie haben ein Objekt, das Daten enthält, und Sie fügen eine Methode (ein Verhalten) hinzu, die in hohem Maße mit den Daten übereinstimmt. Sollten Sie die Funktion ändern, die Funktionalität erweitern oder sonstige Änderungen vornehmen müssen, müssen die Anrufer keine Änderungen vornehmen (vorausgesetzt, es müssen keine zusätzlichen Daten übergeben werden).
2. Versandtabellen
Nicht der klassische Fall, da es nur einen Eintrag mit einer Funktion gibt. Versandtabellen werden jedoch verwendet, um unterschiedliche Verhaltensweisen anhand eines Schlüssels so zu organisieren, dass sie nachgeschlagen und dynamisch aufgerufen werden können. Ich bin mir nicht sicher, ob Sie darüber nachdenken, da Sie sich nicht dynamisch auf die Funktion beziehen, aber dennoch eine effektive späte Bindung erhalten (der "indirekte" Aufruf).
Kompromisse
Beachten Sie, dass Ihre Vorgehensweise bei einem bekannten Schlüssel-Namespace einwandfrei funktioniert. Es besteht jedoch die Gefahr einer Kollision zwischen den Daten und den Funktionen mit einem unbekannten Schlüssel-Namespace.
quelle
Ich poste diese Lösung, die meiner Meinung nach ziemlich allgemein ist und nützlich sein kann, da sie einfach gehalten und leicht an bestimmte Fälle angepasst werden kann:
Man kann auch eine Liste definieren, in der jedes Element ein Funktionsobjekt ist, und die
__call__
eingebaute Methode verwenden. Wir danken allen für die Inspiration und Zusammenarbeit."Der große Künstler ist der Vereinfacher", Henri Frederic Amiel
quelle