Какой должна быть аннотация типа для аргумента установщика свойств python?

Имеет ли python отношение к аннотации типа PEP-484 для свойства? аргумент сеттера? Я вижу два варианта, оба из которых кажутся допустимыми (на мой взгляд, и на mypy).

Рассмотреть возможность:

from dataclasses import dataclass
from typing import Any

@dataclass
class Foo:
    _bar: int = 1

    @property
    def bar(self) -> int:
        return self._bar

    @bar.setter
    def bar(self, value) -> None:
        self._bar = value

Вопрос в том:

Следует ли в value аргументе @bar.setter набирать typing.Any или int?

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

Однако следует отметить одну вещь; mypy не предупреждает о неправильном назначении установщику свойств:

f = Foo()
f.bar = 2     # Ok
f.bar = "baz" # Incompatible types in assignment (expression has type "str", variable has type "int") 

Я считаю, что это происходит от выявленного типа Foo.bar, являющегося int, а не от типа value аргумента @bar.setter.

Я искал через python / cpython и python / typeshed для примеров, но не придумали ничего окончательного.

У меня большой опыт работы с современным питоном, и мне комфортно читать исходные коды cpython (будь то на C или сам python). Ответ, который ссылается на PEP или включает ввод от сопровождающего cpython или mypy, был бы идеальным.


person Zev Isert    schedule 12.03.2021    source источник
comment
Я действительно не понимаю, о чем вы спрашиваете ... аннотирование с помощью Any всегда допустимо. Но Any в основном означает не проверять тип.   -  person juanpa.arrivillaga    schedule 12.03.2021
comment
но с другой стороны, входящее значение может быть любого типа. Что ты хочешь этим сказать. предположим, у меня есть def foo(x: int): return x, ну, входящее значение может быть любого типа, но я отмечаю, что оно должно быть int.   -  person juanpa.arrivillaga    schedule 12.03.2021
comment
Просто ищу передовой опыт, который, как я полагаю, может означать, что я ищу примеры аннотаций типов для аргументов установщика из других языков. Если подумать об этом больше, я думаю, что объединяю цель подсказок типа с проверкой. В моем более сложном примере, который вызвал этот вопрос, функция установки выполняет проверку типа во время выполнения .. И, как и любой другой тип подсказки, подсказка должна быть тем, что я хочу, чтобы вы мне позвонили.   -  person Zev Isert    schedule 12.03.2021


Ответы (1)


Этот вопрос очень хорошо основан на мнении, однако я думаю, что может быть более веский аргумент в пользу мутаторов, аннотированных ожидаемым типом (т.е. def bar(self, value: int) -> None:). Во-первых, аннотации были реализованы для помощи в статическом анализе, а не для обеспечения каких-либо реальных преимуществ во время выполнения (в настоящее время, насколько мне известно, они не делают этого. Из Обоснование PEP 484:

Из этих целей наиболее важной является статический анализ. Это включает поддержку автономных средств проверки типов, таких как mypy, а также предоставление стандартной нотации, которая может использоваться IDE для завершения кода и рефакторинга.

Если аннотации типов в значительной степени предназначены для использования в статическом анализе, линтинге и т. Д., Было бы логично, что вы захотите иметь возможность проверить, что вы передаете неправильный тип, а не потенциально обнаруживать во время выполнения, что вы не обработали параметр должным образом. с проверкой типа, например, с использованием isinstance.

Это также означало бы, что мы можем делать больше с меньшими затратами, поскольку более конкретная аннотация int избавит нас от необходимости добавлять эти средства защиты типов:

def bigger_fun(n: Any) -> None:
    if isinstance(n, float):
        # do something...
    else
        # dosomething else...

def smaller_fun(n: int) -> None:
    # do something

Вы будете точно знать, какой тип вы получите и как с ним обращаться, вместо того, чтобы реализовывать несколько различных условных ветвей, чтобы сначала привести параметр к ожидаемому значению, прежде чем работать с ним. Это позволит вам сделать ваши мутаторы настолько тонкими, насколько это возможно, с минимальной внутренней логикой / обработкой.

Если вы передадите ему неправильный тип, ваша IDE или инструмент статического анализа по крайней мере предупредит вас, например, при передаче float вместо smaller_fun. С другой стороны, использование Any может вызвать неожиданное поведение для некоторых типов, что приводит к ошибкам времени выполнения, которые может быть трудно отследить.

Теперь, более конкретно к вашему вопросу, тот же PEP касается использования аннотаций @property в Значение аннотаций

Ожидается, что средства проверки типов попытаются вывести столько информации, сколько необходимо. Минимальное требование - обработка встроенных декораторов @property, @staticmethod и @classmethod.

Это означает, что вы можете ожидать, что аннотация @property будет нормально работать, как и следовало ожидать. Без особого обращения.

Хотя python по сути является языком с динамической типизацией, такие методы, как мутатор, очень сильно привязаны к определенному значению (и, следовательно, типу) и должны действительно делать только одно, а не одно из множества. Таким образом, хотя это, вероятно, позволяет такому методу сравнения, как __gt__, который, вероятно, будет выполнять разные операции для разных типов, принимать значение Any, мутатор должен иметь как можно более узкую область действия.

Наконец, хотя подсказки типов не являются и, вероятно, никогда не должны быть обязательными, все самые популярные IDE Python, такие как Pycharm, автоматически поддерживают подсказки типов. Они часто выдают предупреждения, даже если другой программист может не аннотировать типы, но тип можно безопасно вывести. Это означает, что даже при использовании библиотеки с подсказками типов мутаторы с аннотацией int все равно будут более информативными и полезными для конечного пользователя, чем аннотация Any.

person joshmeranda    schedule 12.03.2021