Type bei type hints

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Hallo zusammen,

ich möchte gerade bei einer Funktion einen Type Hint einfügen und das will nicht.

Code: Alles auswählen

def foo(arguments: tuple[any, type]):
    pass
der Interpreter meckert dabei immer an, dass er nicht mag

'type' object is not subscriptable

File "*", line 10, in <module>
def foo(arguments: tuple[any,Type]):

Lustigerweise geht aber so was ohne Probleme.

Code: Alles auswählen

def bar(argument : type):
    pass
Hat einer eine Ahnung, wie ich das so zum Laufen bekomme? Oder geht das einfach gar nicht.


Grüße,
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Was willst Du mit der Typ-Annotation eigentlich bezwecken? Welche Python-Version benutzt Du?
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

Das "type" in der Fehlermeldung bezieht sich nicht auf dein "type" im Code, sondern auf den Typ "tuple". Und das "subscriptable" bezieht sich auf die eckigen Klammern. Du versuchst ja damit irgendwie per Index-Operator auf ein Element der Klasse tuple zuzugreifen und das geht nicht (das ginge mit einem tuple-Objekt und einem passenden Index, nicht aber direkt mit der tuple-Klasse).

Du hast vermutlich das Beispiel aus der Python 3.9-Dokumentation, denn da würde das funktionieren, was du schreibst. In früheren Versionen geht das nicht, bzw. ab Python 3.7 nur mit einem "from __future__ import annotations". Stattdessen müsstest du die Tuple-Klasse aus dem typing-Modul für Type Hints benutzen.
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Nun ja,

ich möchte dem geneigten Benutzer einen Hinweis geben, wie er die Funktion aufzurufen hat.

Ich habe es jetzt über den Docstring gelöst. Es ist eine Bibliotheksfunktion und wird zur Typüberprüfung hergenommen.

Grüße,
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Sirius3 hat geschrieben: Dienstag 1. Dezember 2020, 10:51 Was willst Du mit der Typ-Annotation eigentlich bezwecken? Welche Python-Version benutzt Du?
Sry für den Doppelpost, ich habe keine Bearbeiten Funktion gefunden.

Im Prinzip will ich mit der Funktion den Typ prüfen können. Das wird dann in einer anderen Funktion aufgerufen, weil dort der Typ wichtig ist um Anwenderfehler zu verringern, die zur mechanischen Zerstörung meines Gerätes führen können, wenn man die vertauscht.

Ich benutze Python 3.8.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Im Prinzip will ich mit der Funktion den Typ prüfen können.
Aber nicht zur Laufzeit. Da sind Type Annotations nämlich komplett egal. Zitat aus der Python-Doku: "The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc."

Wenn der Typ also wichtig ist, um wie-auch-immer-geartetes schlimmeres zu verhindern, dann muss du die Prüfung tunlichst in den Code einbauen, nicht (nur) in Type Annotations.

Gruß, noisefloor
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

noisefloor hat geschrieben: Dienstag 1. Dezember 2020, 14:07 Hallo,
Im Prinzip will ich mit der Funktion den Typ prüfen können.
Aber nicht zur Laufzeit. Da sind Type Annotations nämlich komplett egal. Zitat aus der Python-Doku: "The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc."

Wenn der Typ also wichtig ist, um wie-auch-immer-geartetes schlimmeres zu verhindern, dann muss du die Prüfung tunlichst in den Code einbauen, nicht (nur) in Type Annotations.

Gruß, noisefloor
Das ist mir klar. Deswegen ja auch diese Funktion. Die ist dazu da um den Typ zu überprüfen. Nur die Argumentliste dieser Funktion ist wenig Aussagekräftig.

Aktuell sieht sie so aus.

Code: Alles auswählen

def CheckType(*to_check):
    # hier wird geprüft ob  der Wert nicht None ist und dem gegebenen Typen entspricht sonst fliegt eine Exception. Und das Ganze soll mit mehreren Parametern funktionieren, damit der Code dann später nicht von CheckType aufrufen gepflastert ist.
Die Typen sollen dann als tuple übergeben werden. Ein Aufruf sieht dann so aus:

Code: Alles auswählen

CheckType(("string",str),(123,int))
Wobei "string" und 123 nur Beispiele sind und im echten Code übergebenen Parametern und ihrem Typ ( als Dataclasses implementiert) entsprechen.

Ich will es nur für den Anwender einfacher machen. Im VSC zum Beispiel zeigt er dann beim Programmieren die Type Hints an und man sieht auf einfache Art und Weise, wie die Funktion zu nutzen ist.

Am Ende ist es nur eine Stilfrage. Funktionieren tut alles, wie es soll.

Grüße,
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Vom Design her klingt das ein bisschen seltsam.
Warum sollte der Code des Anwenders mit Codeprüfungen gepflastert sein? Der Typ sollte - wenn überhaupt - nach Übergabe von der Schnittstelle geprüft werden.
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Sorry Leute.

Vielen Dank für die investierte Zeit. Der Fehler lag gar nicht am 'type' sondern am 'tuple' Die Fehlermeldung hat nur in die völlig falsche Richtung gezeigt.

folgendes Funktioniert:

Code: Alles auswählen

from typing import Tuple

def foo(*argument: Tuple[any,type]):
    pass
Zuletzt geändert von Zwangsgestörter am Dienstag 1. Dezember 2020, 15:17, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Und das geht eben erst ab Python3.9, daher meine Frage, welche Pythonversion Du benutzt.

Typeprüfungen sind so gut wie nie nötig, es sei denn, die Schnittstelle ist nicht sauber definiert, und oder erlaubt viele verschiedene Varianten, statt verschiedener Methoden.
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Sirius3 hat geschrieben: Dienstag 1. Dezember 2020, 15:12 Und das geht eben erst ab Python3.9, daher meine Frage, welche Pythonversion Du benutzt.

Typeprüfungen sind so gut wie nie nötig, es sei denn, die Schnittstelle ist nicht sauber definiert, und oder erlaubt viele verschiedene Varianten, statt verschiedener Methoden.
Die Typprüfung ist zur Sicherheit. Es geht am Ende um einen 6 Achsen Roboterarm. Bei einem Solchen kann man die Position in mehreren verschiedenen Varianten angeben. Zum einen Als Winkel für die einzelnen Achsen oder als Position des Kopfes. Leider sind beides eine Ansammlung von 6 Werten. Damit man diese nicht einfach so verwechseln kann habe ich eben Typen dafür gebaut (im Grunde Dataclasses) und will diese natürlich auch nicht verwechselt haben.

Am Anfang waren alles einfach tuple (winkel_achse_1,winkel_achse_2,winkel_achse_3,winkel_achse_4,winkel_achse_5,winkel_achse_6) und (position_x,position_y,position_z,rotation_x,rotation_y,rotation_z)

Wenn man die irgend wo am Anfang deklariert und falsch übergibt, kann beträchtlicher Schaden am Robot entstehen. Deswegen die Typprüfung, damit der Anwender einen Fehler weniger machen kann.

Grüße.
PS: wie schon im anderen geschrieben. Mein Problem ist geklärt.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du dafür Klassen hast, dann brauchst Du keine Typprüfung, oder hat dein Positionsobjekt etwa ein Attribut winkel_achse1?
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

Sirius3 hat geschrieben: Dienstag 1. Dezember 2020, 15:58 Wenn Du dafür Klassen hast, dann brauchst Du keine Typprüfung, oder hat dein Positionsobjekt etwa ein Attribut winkel_achse1?
ich habe eine Methode 'SetByAxisAngle(angles)' und eine "SetHead(head_coordinates)". Beide benötigen 6 Werte. Die Steuerungseinheit vom Robot interessiert sich nicht für die Variablennamen. Die mag nur 6 Zahlen haben. Deswegen kann der Python Code dahinter ziemlich einfach gehalten werden. Damit man da aber weniger Fehler machen kann überprüfe ich den Typ.

Ich hatte mal alles mit Klassenattributen probiert. Der Code wird deutlich unleserlicher und länger als er jetzt ist.

EDIT: Vielleicht ist der Ansatzt auch nicht der schönste. Aber so ist das nunmal. Bin ja am lernen und die Typisierung von Python ist meine größte Hürde beim Umsteigen auf Python (ein Hoch auf statische Typen :D )
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Zwangsgestörter: Was machst du, wenn der Benutzer die Zahlen in der falschen Reihenfolge angibt?
In specifications, Murphy's Law supersedes Ohm's.
Zwangsgestörter
User
Beiträge: 20
Registriert: Freitag 23. Oktober 2020, 19:00

pillmuncher hat geschrieben: Dienstag 1. Dezember 2020, 16:48 @Zwangsgestörter: Was machst du, wenn der Benutzer die Zahlen in der falschen Reihenfolge angibt?
Nun ja, wenn du eine Möglichkeit kennst, wie ich so was verhindern kann, dann immer her damit. Mir fällt dazu nichts ein.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Wenn Du Schäden an der Hardware bei falschen Parametern verhindern möchtest, dann brauchst Du keine Type-Annotations, sondern explizite Bereichs- und Typ-Prüfungen innerhalb der Funktion, die zur Laufzeit vorgenommen werden.
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Zwangsgestörter: Es wäre einfacher, wenn du uns wenigstens deine Klasse(n?) zeigen würdest. Du kannst dabei gerne unwesentliches weglassen, solange es gültiges Python bleibt.
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Funktionsnamen halten sich nicht an die Konvention: es muß set_head und set_by_axis_angle heißen. Und auch hier sehe ich kein Bedarf, den Typ zu prüfen, denn das head_coordinates-Objekt hat ja hoffentlich ein coordinates-Attribut und angles hat wohl ein entsprechendes Attribut das die passenden 6 Zahlenwerte liefert.
Idealerweise ist das das selbe Objekt das auch die Umrechnung übernehmen kann.
Antworten