¿Por qué "mypy" considera "int" como un subtipo de "flotante"? Un subtipo admitirá todos los métodos de su supertipo, pero "float" tiene métodos, que "int" no admite:
test.py:
def f(x : float) -> bool:
return x.is_integer()
print(f(123.0))
print(f(123))
El verificador de tipo estático acepta pasar un argumento "int" para un parámetro "flotante":
(3.8.1) myhost% mypy test.py
Success: no issues found in 1 source file
Pero esto no garantiza que no haya errores en tiempo de ejecución:
(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'
porque "float" tiene métodos adicionales, que "int" no tiene.
int
no puede caber en una carroza. Pythonint
s no son máquinasint
s. (De todos modos, no estoy seguro de cómo eso sería relevante para la verificación de tipos, que no está realmente preocupado por las representaciones de tipos en tiempo de ejecución.)int
yfloat
parece ignorar por completo el hecho de que ambos tipos tienen métodos, o al menos los métodos distintos__add__
et al.Respuestas:
"¿Por qué" mypy "considera" int "como un subtipo de" flotador "?
Porque hasta ahora se ha considerado que la practicidad supera la pureza aquí. Esto no quiere decir que no se pueda proponer que la tipificación defina un tipo Escalar que incluya ints y flotantes, pero que solo sea válido para operaciones aritméticas.
Tenga en cuenta que int / int se cambió en 3.0 para que float (int / int) == float (int) / float (int), para hacer que la aritmética int y float sea coherente para valores iguales de int y float.
Tenga en cuenta también que pasar una verificación de tipo no significa que no haya errores de tiempo de ejecución: la división por cero y el desbordamiento aún son posibles, así como muchos otros.
fuente
Como señaló @ juanpa.arrivillaga , la explicación está en https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html .
int
no es un subtipo defloat
, por lo que no tiene que admitir métodos defloat
.El mecanismo es bueno porque pasar valores enteros no debería causar errores, a menos que realmente los desee como en su ejemplo. Intentaste explícitamente utilizar un método que no existe. En situaciones comunes, solo realizamos operaciones aritméticas en números, por lo que rara vez existe un problema y siempre puede evitarlo agregando
.0
lo que escribió.Es un comportamiento común en la mayoría de los lenguajes suponer que
int
es un caso especial defloat
, considere, por ejemplo, C ++int
a lafloat
conversión implícita.fuente