python 属性 setter 的参数的类型注释应该是什么?
What should the type annotation for a python property setter's argument be?
python 是否对 PEP-484 类型注释对 属性 setter 的论点有立场?我看到两个选项,这两个选项似乎都有效(根据我和 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
问题是:
Should @bar.setter
's value
argument be typed with typing.Any
or with int
?
一方面,在 setter 中,具有预期类型 hint 将有助于执行验证,但另一方面,传入值可能是任何类型。
不过有一点值得注意; mypy 确实警告对 属性 setter:
的错误分配
f = Foo()
f.bar = 2 # Ok
f.bar = "baz" # Incompatible types in assignment (expression has type "str", variable has type "int")
我相信这是因为 Foo.bar
的显示类型是 int
,而不是来自 @bar.setter
的 value
参数的类型。
我在 python/cpython and python/typeshed 个项目中搜索了示例,但没有得出任何明确的结论。
我对现代 python 非常有经验,并且很乐意阅读 cpython 来源(在 C 或 python 本身)。引用 PEP 或包含来自 cpython 或 mypy 维护者的输入的答案将是理想的。
这个问题非常适合基于强烈的意见,但是,我认为对于用预期类型(即 def bar(self, value: int) -> None:
)注释的突变器可能会有更有力的论据。首先,注释的实现是为了帮助静态分析,而不是提供任何真正的运行时好处(据我所知,目前还不知道。来自 PEP 484 rationale:
Of these goals, static analysis is the most important. This includes support for off-line type checkers such as mypy, as well as providing a standard notation that can be used by IDEs for code completion and refactoring.
如果类型注释主要是为了在静态分析、linting 等中受益,那么您希望能够检查您是否传递了错误的类型,而不是在运行时可能发现您有例如,使用 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 或静态分析工具至少会在为 smaller_fun
传递 float
时警告您。另一方面,使用 Any
可能会对某些类型产生意外行为,从而引入难以追踪的运行时错误。
现在更具体地针对您的问题,同一 PEP 涉及 The Meaning of Annotations
中 @property
注释的使用
Type checkers are expected to attempt to infer as much information as necessary. The minimum requirement is to handle the builtin decorators @property, @staticmethod and @classmethod.
这意味着您可以预期 @property
注释应该会像您期望的那样正常运行。没有任何特殊处理。
虽然 python 本质上是一种动态类型的语言,但像 mutator 这样的方法与特定值(以及因此类型)紧密相关,并且应该只做一件事而不是做许多事情中的一件。因此,虽然对于像 __gt__
这样的比较方法,它可能会对不同的类型执行不同的操作,但它可能会采用 Any
值,因此 mutator 应该采用尽可能窄的范围。
最后,尽管类型提示不是而且可能永远不应该是强制性的,但所有最流行的 python IDE 都自动支持类型提示,例如 Pycharm。他们通常会发出警告,即使另一个程序员可能没有注释类型,但可以安全地推断类型。这意味着即使在使用带有类型提示的库时,带有 int
注释的修改器仍然比 Any
注释对最终用户提供更多信息和有用。
python 是否对 PEP-484 类型注释对 属性 setter 的论点有立场?我看到两个选项,这两个选项似乎都有效(根据我和 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
问题是:
Should
@bar.setter
'svalue
argument be typed withtyping.Any
or withint
?
一方面,在 setter 中,具有预期类型 hint 将有助于执行验证,但另一方面,传入值可能是任何类型。
不过有一点值得注意; mypy 确实警告对 属性 setter:
的错误分配f = Foo()
f.bar = 2 # Ok
f.bar = "baz" # Incompatible types in assignment (expression has type "str", variable has type "int")
我相信这是因为 Foo.bar
的显示类型是 int
,而不是来自 @bar.setter
的 value
参数的类型。
我在 python/cpython and python/typeshed 个项目中搜索了示例,但没有得出任何明确的结论。
我对现代 python 非常有经验,并且很乐意阅读 cpython 来源(在 C 或 python 本身)。引用 PEP 或包含来自 cpython 或 mypy 维护者的输入的答案将是理想的。
这个问题非常适合基于强烈的意见,但是,我认为对于用预期类型(即 def bar(self, value: int) -> None:
)注释的突变器可能会有更有力的论据。首先,注释的实现是为了帮助静态分析,而不是提供任何真正的运行时好处(据我所知,目前还不知道。来自 PEP 484 rationale:
Of these goals, static analysis is the most important. This includes support for off-line type checkers such as mypy, as well as providing a standard notation that can be used by IDEs for code completion and refactoring.
如果类型注释主要是为了在静态分析、linting 等中受益,那么您希望能够检查您是否传递了错误的类型,而不是在运行时可能发现您有例如,使用 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 或静态分析工具至少会在为 smaller_fun
传递 float
时警告您。另一方面,使用 Any
可能会对某些类型产生意外行为,从而引入难以追踪的运行时错误。
现在更具体地针对您的问题,同一 PEP 涉及 The Meaning of Annotations
中@property
注释的使用
Type checkers are expected to attempt to infer as much information as necessary. The minimum requirement is to handle the builtin decorators @property, @staticmethod and @classmethod.
这意味着您可以预期 @property
注释应该会像您期望的那样正常运行。没有任何特殊处理。
虽然 python 本质上是一种动态类型的语言,但像 mutator 这样的方法与特定值(以及因此类型)紧密相关,并且应该只做一件事而不是做许多事情中的一件。因此,虽然对于像 __gt__
这样的比较方法,它可能会对不同的类型执行不同的操作,但它可能会采用 Any
值,因此 mutator 应该采用尽可能窄的范围。
最后,尽管类型提示不是而且可能永远不应该是强制性的,但所有最流行的 python IDE 都自动支持类型提示,例如 Pycharm。他们通常会发出警告,即使另一个程序员可能没有注释类型,但可以安全地推断类型。这意味着即使在使用带有类型提示的库时,带有 int
注释的修改器仍然比 Any
注释对最终用户提供更多信息和有用。