mypy: Por que "int" é um subtipo de "float"?

8

Por que "mypy" considera "int" como um subtipo de "float"? Um subtipo deve suportar todos os métodos de seu supertipo, mas "float" possui métodos que "int" não suportam:

test.py:

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

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

O verificador de tipo estático aceita passar um argumento "int" para um parâmetro "float":

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

Mas isso não garante que não haja erros no tempo de execução:

(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" possui métodos adicionais, os quais "int" não possui.

python_user_1234
fonte
5
Oh uau, isso parece ruim para mim, aqui está a explicação: mypy.readthedocs.io/en/latest/duck_type_compatibility.html
juanpa.arrivillaga
2
@BlackFrog não, não pode.
juanpa.arrivillaga 6/01
3
@BlackFrog Um int não pode caber em um carro alegórico. Python ints não são máquinas ints. (De qualquer forma, não tenho certeza de como isso seria relevante para a verificação de tipo, que não está realmente preocupada com representações de tipos em tempo de execução.)
chepner
1
A menos que eu esteja perdendo alguma coisa, a justificativa para o uso da digitação com pato inte floatparece ignorar completamente o fato de que ambos os tipos têm métodos, ou pelo menos métodos diferentes de __add__et al.
chepner 6/01
1
@StefanPochmann sim, mas como mostrado aqui, a partir de um sistema de tipos POV, não é
juanpa.arrivillaga

Respostas:

1

'Por que "mypy" considera "int" como um subtipo de "float"?

Porque a praticidade até agora tem sido considerada para vencer a pureza aqui. Isso não quer dizer que não se possa propor que a digitação defina um tipo escalar que inclua ints e floats, mas seja válido apenas para operações aritméticas.

Observe que int / int foi alterado no 3.0 para que float (int / int) == float (int) / float (int), para tornar a aritmética de int e float consistente para valores int e float iguais.

Observe também que uma aprovação de verificação de tipo não significa que não haja erros de tempo de execução: a divisão por zero e o estouro ainda são possíveis, assim como muitos outros.

Terry Jan Reedy
fonte
-1

Como @ juanpa.arrivillaga apontou, a explicação está em https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html .

Um subtipo deve suportar todos os métodos de seu supertipo, mas "float" possui métodos que "int" não suporta

intnão é um subtipo de float, portanto, não precisa suportar métodos de float.

O mecanismo é bom porque a passagem de valores inteiros não deve causar erros, a menos que você realmente os queira, como no seu exemplo. Você tentou explicitamente usar um método que não existe. Em situações comuns, apenas fazemos operações aritméticas em números, portanto, um problema raramente existe e você sempre pode evitá-lo adicionando .0como escreveu.

É um comportamento comum na maioria dos idiomas assumir que esse inté um caso especial float, considere, por exemplo, C ++ intpara floatconversão implícita.

banan3'14
fonte
Honestamente, dizer "você sempre pode evitá-lo usando o tipo correto" não é um argumento convincente para mim para um verificador de tipos estar errado.
juanpa.arrivillaga 6/01
O objetivo principal da digitação estática é justamente evitar o uso de um método não definido para o tipo. A primeira parte da resposta está correta; continuar explicando por que não há uma desvantagem é apenas fazer um desserviço a todos.
chepner 6/01
Eu não voto negativo, para constar.
juanpa.arrivillaga 6/01