Wenn ich mich nicht irre, funktioniert das Erstellen einer Funktion in Python folgendermaßen:
def my_func(param1, param2):
# stuff
Sie geben jedoch nicht die Typen dieser Parameter an. Wenn ich mich recht erinnere, ist Python eine stark typisierte Sprache. Daher sollte Python anscheinend nicht zulassen, dass Sie einen Parameter eines anderen Typs als den erwarteten Funktionsersteller übergeben. Woher weiß Python jedoch, dass der Benutzer der Funktion die richtigen Typen übergibt? Wird das Programm nur sterben, wenn es der falsche Typ ist, vorausgesetzt, die Funktion verwendet tatsächlich den Parameter? Müssen Sie den Typ angeben?
python
function
parameters
Leif Andersen
quelle
quelle
Antworten:
Python ist typisiert stark , weil jedes Objekt hat eine Art, jedes Objekt kennt seine Art, ist es unmöglich oder absichtlich versehentlich ein Objekt eines Typs zu verwenden , „als ob“ es eine Aufgabe eines war anders Art, und alle elementaren Operationen auf dem Objekt an seinen Typ delegiert.
Das hat nichts mit Namen zu tun . Ein Name in Python hat keinen "Typ": Wenn ein Name definiert ist, bezieht sich der Name auf ein Objekt , und das Objekt hat einen Typ (dies erzwingt jedoch keinen Typ für den Namen : a Name ist ein Name).
Ein Name in Python kann durchaus auf verschiedene Objekte zu unterschiedlichen Zeiten verweisen (wie in den meisten Programmiersprachen, wenn auch nicht in allen) - und es gibt keine Einschränkung für den Namen, sodass, wenn er einmal auf ein Objekt vom Typ X verwiesen hat, es ist dann nur auf andere Objekte vom Typ X. Einschränkungen verweisen immerdar eingeschränkt Namen nicht Teil des Konzepts der „starken Typisierung“ ist, obwohl einige Enthusiasten statischer Typisierung (wo Namen sie gezwungen werden, und in einem statischen, AKA compile- Zeit, Mode auch) missbrauchen den Begriff auf diese Weise.
quelle
try
/except
) tritt auf, wenn eine Operation versucht wird, die das Objekt nicht unterstützt. In Python 3.5 können Sie jetzt optional Argumenttypen "angeben", aber es tritt per se kein Fehler auf, wenn die Spezifikation verletzt wird. Die Schreibnotation soll nur dazu dienen, Tools zu trennen, die Analysen usw. durchführen. Sie ändert das Verhalten von Python selbst nicht.Die anderen Antworten haben gute Arbeit geleistet, um das Tippen von Enten und die einfache Antwort von tzot zu erklären :
Eine interessante Sache hat sich jedoch seit 2010 (als die Frage zum ersten Mal gestellt wurde) geändert, nämlich die Implementierung von PEP 3107 (implementiert in Python 3). Sie können jetzt den Typ eines Parameters und den Typ des Rückgabetyps einer Funktion wie folgt angeben:
Wir können hier sehen, dass
pick
2 Parameter, eine Listel
und eine Ganzzahl, benötigt werdenindex
. Es sollte auch eine Ganzzahl zurückgeben.Hier wird also impliziert, dass
l
es sich um eine Liste von Ganzzahlen handelt, die wir ohne großen Aufwand sehen können. Bei komplexeren Funktionen kann es jedoch etwas verwirrend sein, was die Liste enthalten soll. Wir möchten auch, dass der Standardwertindex
0 ist. Um dies zu lösen, können Siepick
stattdessen wie folgt schreiben :Beachten Sie, dass wir jetzt einen String als Typ eingeben
l
, der syntaktisch zulässig ist, aber nicht für das programmgesteuerte Parsen geeignet ist (worauf wir später zurückkommen werden).Es ist wichtig zu beachten, dass Python kein a erhöht,
TypeError
wenn Sie einen Float übergebenindex
. Der Grund dafür ist einer der Hauptpunkte in Pythons Designphilosophie: "Wir sind alle einverstanden, dass Erwachsene hier sind" , was bedeutet, dass Sie dies erwarten Seien Sie sich bewusst, was Sie an eine Funktion übergeben können und was nicht. Wenn Sie wirklich Code schreiben möchten, der TypeErrors auslöst, können Sie mit derisinstance
Funktion überprüfen, ob das übergebene Argument vom richtigen Typ oder einer Unterklasse davon wie folgt ist:Mehr darüber, warum Sie dies selten tun sollten und was Sie stattdessen tun sollten, wird im nächsten Abschnitt und in den Kommentaren besprochen.
PEP 3107 verbessert nicht nur die Lesbarkeit des Codes, sondern verfügt auch über mehrere passende Anwendungsfälle, über die Sie hier lesen können .
Die Typanmerkung hat in Python 3.5 mit der Einführung von PEP 484, das ein Standardmodul für Typhinweise einführt, viel mehr Aufmerksamkeit erhalten .
Diese Typhinweise stammen vom Typprüfer mypy ( GitHub ), der jetzt PEP 484- kompatibel ist.
Das Schreibmodul enthält eine ziemlich umfassende Sammlung von Tipphinweisen, darunter:
List
,Tuple
,Set
,Map
- fürlist
,tuple
,set
undmap
jeweils.Iterable
- nützlich für Generatoren.Any
- wenn es irgendetwas sein könnte.Union
- wenn es sich um etwas innerhalb eines bestimmten Satzes von Typen handeln könnte, im Gegensatz zuAny
.Optional
- wenn es keine sein könnte . Abkürzung fürUnion[T, None]
.TypeVar
- mit Generika verwendet.Callable
- wird hauptsächlich für Funktionen verwendet, kann aber auch für andere aufrufbare Elemente verwendet werden.Dies sind die häufigsten Typhinweise. Eine vollständige Auflistung finden Sie in der Dokumentation zum Schreibmodul .
Hier ist das alte Beispiel mit den im Schreibmodul eingeführten Anmerkungsmethoden:
Eine leistungsstarke Funktion ist die
Callable
, mit der Sie Annotationsmethoden eingeben können, die eine Funktion als Argument verwenden. Zum Beispiel:Das obige Beispiel könnte mit der Verwendung von
TypeVar
anstelle von präziser werdenAny
, aber dies wurde dem Leser als Übung überlassen, da ich glaube, dass ich meine Antwort bereits mit zu vielen Informationen über die wunderbaren neuen Funktionen gefüllt habe, die durch Typhinweise ermöglicht werden.Wenn zuvor Python-Code mit beispielsweise Sphinx dokumentiert wurde, konnten einige der oben genannten Funktionen durch Schreiben von Dokumentstrings erhalten werden, die wie folgt formatiert waren:
Wie Sie sehen können, sind einige zusätzliche Zeilen erforderlich (die genaue Anzahl hängt davon ab, wie explizit Sie sein möchten und wie Sie Ihre Dokumentzeichenfolge formatieren). Aber jetzt sollte Ihnen klar sein, wie PEP 3107 eine Alternative bietet, die in vielerlei Hinsicht überlegen ist. Dies gilt insbesondere in Kombination mit PEP 484, das, wie wir gesehen haben, ein Standardmodul bereitstellt, das eine Syntax für diese Typhinweise / Anmerkungen definiert, die so verwendet werden kann, dass sie eindeutig und präzise und dennoch flexibel ist kraftvolle Kombination.
Meiner persönlichen Meinung nach ist dies eine der größten Funktionen in Python, die es je gab. Ich kann es kaum erwarten, dass die Leute anfangen, die Kraft davon zu nutzen. Entschuldigung für die lange Antwort, aber das passiert, wenn ich aufgeregt bin.
Ein Beispiel für Python-Code, der häufig Typhinweise verwendet, finden Sie hier .
quelle
TypeError
, wozu dient dann diepick(l: list, index: int) -> int
Definition einer Zeile? Oder ich habe es falsch verstanden, ich weiß es nicht.__annotations__
Attribut des Funktionsobjekts gespeichert ).def f(a) -> Tuple[int, int]:
Sie geben keinen Typ an. Die Methode schlägt (zur Laufzeit) nur fehl, wenn versucht wird, auf Attribute zuzugreifen, die in den übergebenen Parametern nicht definiert sind.
Also diese einfache Funktion:
... wird nicht scheitern, egal welche zwei Argumente übergeben werden.
Diese Funktion:
... wird zur Laufzeit fehlschlagen , wenn
param1
undparam2
nicht beide mit dem Namen aufrufbar Attributenquack
.quelle
Viele Sprachen haben Variablen, die von einem bestimmten Typ sind und einen Wert haben. Python hat keine Variablen; Es enthält Objekte, und Sie verwenden Namen, um auf diese Objekte zu verweisen.
In anderen Sprachen, wenn Sie sagen:
dann ändert eine (normalerweise ganzzahlige) Variable ihren Inhalt auf den Wert 1.
In Python
bedeutet "Verwenden Sie den Namen a , um auf das Objekt 1 zu verweisen ". In einer interaktiven Python-Sitzung können Sie Folgendes tun:
Die Funktion
type
wird mit dem Objekt aufgerufen1
; Da jedes Objekt seinen Typ kennt, ist es einfachtype
, diesen Typ herauszufinden und zurückzugeben.Ebenso, wann immer Sie eine Funktion definieren
die Funktion erhält zwei Objekte, und nennt sie
param1
undparam2
, unabhängig von ihrer Art. Wenn Sie sicherstellen möchten, dass die empfangenen Objekte von einem bestimmten Typ sind, codieren Sie Ihre Funktion so, als ob sie vom erforderlichen Typ sind, und fangen Sie die Ausnahmen ab, die ausgelöst werden, wenn dies nicht der Fall ist. Die ausgelösten Ausnahmen sind normalerweiseTypeError
(Sie haben eine ungültige Operation verwendet) undAttributeError
(Sie haben versucht, auf ein nicht vorhandenes Mitglied zuzugreifen (Methoden sind auch Mitglieder)).quelle
Python ist nicht stark typisiert im Sinne einer statischen Typprüfung oder einer Typprüfung zur Kompilierungszeit.
Der meiste Python-Code fällt unter die sogenannte "Ententypisierung" - Sie suchen beispielsweise nach einer Methode
read
für ein Objekt - es ist Ihnen egal, ob das Objekt eine Datei auf der Festplatte oder ein Socket ist, Sie möchten nur N lesen Bytes davon.quelle
Wie Alex Martelli erklärt ,
Lesen Sie den Rest seines Beitrags für hilfreiche Informationen.
quelle
Python ist es egal, was Sie an seine Funktionen übergeben. Wenn Sie aufrufen
my_func(a,b)
, enthalten die Variablen param1 und param2 die Werte von a und b. Python weiß nicht, dass Sie die Funktion mit den richtigen Typen aufrufen, und erwartet, dass der Programmierer sich darum kümmert. Wenn Ihre Funktion mit verschiedenen Parametertypen aufgerufen wird, können Sie Code, der auf sie zugreift, mit Try / Except-Blöcken umschließen und die Parameter nach Ihren Wünschen auswerten.quelle
Sie geben niemals den Typ an; Python hat das Konzept der Ententypisierung ; Grundsätzlich wird der Code, der die Parameter verarbeitet, bestimmte Annahmen über sie treffen - möglicherweise durch Aufrufen bestimmter Methoden, deren Implementierung von einem Parameter erwartet wird. Wenn der Parameter vom falschen Typ ist, wird eine Ausnahme ausgelöst.
Im Allgemeinen liegt es an Ihrem Code, sicherzustellen, dass Sie Objekte des richtigen Typs weitergeben - es gibt keinen Compiler, der dies im Voraus erzwingt.
quelle
Es gibt eine berüchtigte Ausnahme von der Ententypisierung, die auf dieser Seite erwähnenswert ist.
Wenn eine
str
Funktion die__str__
Klassenmethode aufruft, überprüft sie subtil ihren Typ:Als ob Guido uns andeutet, welche Ausnahme ein Programm auslösen soll, wenn es auf einen unerwarteten Typ stößt.
quelle
In Python hat alles einen Typ. Eine Python-Funktion führt alles aus, was sie tun soll, wenn die Art der Argumente dies unterstützt.
Beispiel:
foo
fügt alles hinzu, was bearbeitet werden kann__add__
;) ohne sich um seinen Typ zu kümmern. Das heißt, um Fehler zu vermeiden, sollten Sie nur die Dinge bereitstellen, die das Hinzufügen unterstützen.quelle
Ich habe dies in anderen Antworten nicht erwähnt, also werde ich es in den Topf geben.
Wie andere bereits gesagt haben, erzwingt Python keinen Typ für Funktions- oder Methodenparameter. Es wird davon ausgegangen, dass Sie wissen, was Sie tun, und dass Sie, wenn Sie wirklich wissen müssen, welche Art von etwas übergeben wurde, dies überprüfen und selbst entscheiden, was Sie tun möchten.
Eines der Hauptwerkzeuge hierfür ist die Funktion isinstance ().
Wenn ich zum Beispiel eine Methode schreibe, die erwartet, dass rohe binäre Textdaten anstelle der normalen utf-8-codierten Zeichenfolgen abgerufen werden, kann ich den Typ der Parameter auf dem Weg nach innen überprüfen und mich entweder an das anpassen, was ich finde, oder eine auslösen Ausnahme zu verweigern.
Python bietet auch alle Arten von Werkzeugen, um in Objekte zu graben. Wenn Sie mutig sind, können Sie mit importlib sogar Ihre eigenen Objekte beliebiger Klassen im laufenden Betrieb erstellen. Ich habe dies getan, um Objekte aus JSON-Daten neu zu erstellen. So etwas wäre ein Albtraum in einer statischen Sprache wie C ++.
quelle
Um das Typisierungsmodul (neu in Python 3.5) effektiv zu nutzen, schließen Sie all (
*
) ein.Und Sie sind bereit zu verwenden:
Doch noch können Sie Typnamen wie verwenden
int
,list
,dict
, ...quelle
Ich habe einen Wrapper implementiert, wenn jemand Variablentypen angeben möchte.
Verwenden Sie es als:
BEARBEITEN
Der obige Code funktioniert nicht, wenn einer der Argumente (oder Rückgabetypen) nicht deklariert ist. Die folgende Bearbeitung kann helfen, funktioniert jedoch nur für kwargs und überprüft keine Argumente.
quelle