Я работаю над небольшим модулем, чтобы использовать аннотации для включения дополнительных данных о полях класса, используя вызовы функций в качестве аннотаций (см. Код ниже). Я пытаюсь найти способ сделать это, сохранив при этом совместимость с проверкой статического типа. (Примечание: я делаю это с полным знанием PEP 563 и отложенной оценки аннотаций)
Я запустил следующий код через mypy 0.670, а также через pycharm 2019.2.4. mypy сообщает «об ошибке: недопустимый тип комментария или аннотации» в объявлении поля value
. Однако pycharm предполагает, что поле значения должно быть int.
Похоже, что pycharm определила, что результатом вызова функции its_an_int()
является тип int
, и поэтому может обрабатывать поле как целое число для проверки статического типа и других функций IDE. Это идеальный вариант, и я надеюсь, что проверка типов Python может выполнить.
Я в первую очередь полагаюсь на pycharm и не использую mypy. Однако я осторожно отношусь к использованию этого дизайна, если он будет конфликтовать с тем, что считается «нормальным» для аннотаций типов, и особенно если другие средства проверки типов, такие как mypy, не справятся с этим.
Как сказано в PEP 563, «использование аннотаций, несовместимых с вышеупомянутыми PEP, должно считаться устаревшим.». Я бы понял, что это означает, что аннотации в основном предназначены для указания типов, но я не вижу ни в одном из PEP ничего, что иначе препятствовало бы использованию выражений в аннотациях. Предположительно, выражения, которые сами могут быть подвергнуты статическому анализу, будут приемлемыми аннотациями.
Разумно ли ожидать, что поле value
ниже может быть выведено как целое число с помощью статического анализа, как в настоящее время определено для Python 3.8 (по 4.0)? Mypy слишком строг или ограничен в своем анализе? Или пихарм слишком либерален?
from __future__ import annotations
import typing
def its_an_int() -> typing.Type[int]:
# ...magic stuff happens here...
pass
class Foo:
# This should be as if "value: int" was declared, but with side effects
# once the annotation is evaluted.
value: its_an_int()
def __init__(self, value):
self.value = value
def y(a: str) -> str:
return a.upper()
f = Foo(1)
# This call will fail since it is passing an int instead of a string. A
# static analyzer should flag the argument type as incorrect if value's type
# is known.
print(y(f.value))