mypy: Warum ist "int" ein Subtyp von "float"?

8

Warum betrachtet "mypy" "int" als Subtyp von "float"? Ein Subtyp soll alle Methoden seines Supertyps unterstützen, aber "float" hat Methoden, die "int" nicht unterstützt:

test.py:

def f(x : float) -> bool:
    return x.is_integer()

print(f(123.0))
print(f(123))

Die statische Typprüfung akzeptiert die Übergabe eines "int" -Arguments für einen "float" -Parameter:

(3.8.1) myhost% mypy test.py
Success: no issues found in 1 source file

Dies garantiert jedoch nicht, dass zur Laufzeit keine Fehler auftreten:

(3.8.1) myhost% python test.py
True
Traceback (most recent call last):
  File "test.py", line 5, in <module>
    print(f(123))
  File "test.py", line 2, in f
    return x.is_integer()
AttributeError: 'int' object has no attribute 'is_integer'

weil "float" zusätzliche Methoden hat, die "int" nicht hat.

python_user_1234
quelle
5
Oh wow, das scheint mir schlecht zu sein, hier ist die Erklärung: mypy.readthedocs.io/en/latest/duck_type_compatibility.html
juanpa.arrivillaga
2
@ BlackFrog nein, das kann es nicht.
juanpa.arrivillaga
3
@BlackFrog Ein passt int nicht in einen Schwimmer. Pythons intsind keine Maschinen int. (Wie auch immer, ich bin mir nicht sicher, wie das für die Typprüfung relevant wäre, was sich nicht wirklich mit Laufzeitdarstellungen von Typen befasst.)
chepner
1
Sofern mir nichts fehlt, ist die Begründung für die Verwendung der Ententypisierung mit intund floatscheint die Tatsache völlig zu ignorieren, dass beide Typen Methoden haben oder zumindest andere Methoden als __add__et al.
Chepper
1
@StefanPochmann ja, aber wie hier gezeigt, von einem Typsystem POV ist es nicht
juanpa.arrivillaga

Antworten:

1

"Warum betrachtet" mypy "" int "als Subtyp von" float "? '

Weil die Praktikabilität bisher die Reinheit hier übertrifft. Dies bedeutet nicht, dass man nicht vorschlagen könnte, dass die Typisierung einen Skalartyp definiert, der Ints und Floats enthält, sondern nur für arithmetische Operationen gültig ist.

Beachten Sie, dass int / int in 3.0 so geändert wurde, dass float (int / int) == float (int) / float (int) ist, um die Int- und float-Arithmetik für gleiche int- und float-Werte konsistent zu machen.

Beachten Sie auch, dass eine Typprüfung keine Laufzeitfehler bedeutet: Division durch Null und Überlauf sind weiterhin möglich, ebenso wie viele andere.

Terry Jan Reedy
quelle
-1

Wie @ juanpa.arrivillaga hervorhob , finden Sie die Erklärung unter https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html .

Ein Subtyp soll alle Methoden seines Supertyps unterstützen, aber "float" hat Methoden, die "int" nicht unterstützt

intist kein Subtyp von float, daher muss es keine Methoden von unterstützenfloat .

Der Mechanismus ist gut, da die Übergabe ganzzahliger Werte keine Fehler verursachen sollte, es sei denn, Sie möchten sie wirklich wie in Ihrem Beispiel. Sie haben explizit versucht, eine nicht vorhandene Methode zu verwenden. In normalen Situationen führen wir nur arithmetische Operationen mit Zahlen durch, sodass ein Problem selten besteht und Sie es jederzeit durch Hinzufügen vermeiden können.0 Sie wie geschrieben .

In den meisten Sprachen ist es üblich, anzunehmen, dass dies intein Sonderfall ist float. Betrachten Sie beispielsweise C ++ intals floatimplizite Konvertierung.

banan3'14
quelle
Ehrlich gesagt ist die Aussage "Sie können es immer vermeiden, indem Sie den richtigen Typ verwenden" für mich kein überzeugendes Argument dafür, dass eine Typprüfung falsch ist.
juanpa.arrivillaga
Der ganze Punkt der statischen Typisierung ist genau zu vermeiden mit einer Methode , die nicht für den Typen definiert ist. Der erste Teil der Antwort ist in Ordnung; Zu erklären, warum es keinen Nachteil gibt, bedeutet nur, jedem einen schlechten Dienst zu erweisen.
Chepner
Ich habe nicht für die Aufzeichnung herabgestimmt.
juanpa.arrivillaga