mypy: почему "int" является подтипом "float"? - PullRequest
8 голосов
/ 07 января 2020

Почему «mypy» рассматривает «int» как подтип «float»? Подтип должен поддерживать все методы своего супертипа, но у «float» есть методы, которые «int» не поддерживает:

test.py:

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

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

Тип stati c средство проверки принимает передачу аргумента "int" для параметра "float":

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

Но это не гарантирует отсутствия ошибок во время выполнения:

(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'

потому что "float "имеет дополнительные методы, которых у" int "нет.

Ответы [ 2 ]

1 голос
/ 12 января 2020

'Почему «mypy» рассматривает «int» как подтип «float»?'

Поскольку до сих пор считалось, что практичность побеждает чистоту. Это не означает, что нельзя предлагать, чтобы типирование определяло скалярный тип, который включал бы целые числа и числа с плавающей запятой, но был бы действительным только для операций arithmeti c.

Обратите внимание, что int / int был изменен в 3.0, так что float (int / int) == float (int) / float (int), чтобы согласовать арифметику int и float c для одинаковых значений int и float.

Обратите внимание также, что при проверке типа выполняется не означает никаких ошибок времени выполнения: деление на ноль и переполнение все еще возможны, как и многие другие.

0 голосов
/ 07 января 2020

Как указывало @juanpa.arrivillaga, объяснение на https://mypy.readthedocs.io/en/latest/duck_type_compatibility.html.

Подтип должен поддерживать все методы своего супертипа, но у «float» есть методы, которые «int» не поддерживает

int - это , а не подтип float, поэтому он не должен поддерживать методы float.

Механизм хорош, потому что передача целочисленных значений не должна вызывать ошибок, если вы действительно не хотите их, как в вашем примере. Вы явно пытались использовать метод, который не существует. В обычных ситуациях мы выполняем только арифметические c операции над числами, поэтому проблема существует редко, и вы всегда можете ее избежать, добавив .0, как вы написали.

В большинстве языков это обычное поведение. предположим, что int является частным случаем float, рассмотрим, например, неявное преобразование C ++ int в float.

...