mypy: ¿Por qué es "int" un subtipo de "flotador"?

8

¿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.

python_user_1234
fuente
55
Oh wow, esto me parece malo, aquí está la explicación: mypy.readthedocs.io/en/latest/duck_type_compatibility.html
juanpa.arrivillaga
2
@BlackFrog no, no puede.
juanpa.arrivillaga
3
@BlackFrog An int no puede caber en una carroza. Python ints no son máquinas ints. (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.)
Chepner
1
A menos que me falta algo, la justificación del uso de la tipificación de pato con inty floatparece ignorar por completo el hecho de que ambos tipos tienen métodos, o al menos los métodos distintos __add__et al.
Chepner
1
@StefanPochmann sí, pero como se muestra aquí, desde un POV del sistema de tipos, no lo es
juanpa.arrivillaga

Respuestas:

1

"¿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.

Terry Jan Reedy
fuente
-1

Como señaló @ juanpa.arrivillaga , la explicación está en https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html .

Un subtipo admitirá todos los métodos de su supertipo, pero "float" tiene métodos, que "int" no admite

intno es un subtipo de float, 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 intes un caso especial de float, considere, por ejemplo, C ++ inta la floatconversión implícita.

banan3'14
fuente
Honestamente, decir "siempre puedes evitarlo usando el tipo correcto" no es un argumento convincente para mí para que un verificador de tipo esté equivocado.
juanpa.arrivillaga
El objetivo de la escritura estática es precisamente evitar usar un método que no esté definido para el tipo. La primera parte de la respuesta está bien; explicando por qué no hay un inconveniente, solo perjudica a todos.
chepner
No voté en contra, para que conste.
juanpa.arrivillaga