exh*_*uma 6 python type-hinting mypy
搜索此主题时,我遇到了以下问题:如何表示整数无穷大?
我同意 Martijn Peeters 的观点,即添加一个单独的特殊无穷大值int可能不是最好的想法。
然而,这使得类型提示变得困难。假设以下代码:
myvar = 10 # type: int
myvar = math.inf # <-- raises a typing error because math.inf is a float
Run Code Online (Sandbox Code Playgroud)
但是,代码在任何地方都按其应有的方式运行。我的类型提示在其他任何地方都是正确的。
如果我改写以下内容:
myvar = 10 # type: Union[int, float]
Run Code Online (Sandbox Code Playgroud)
我可以math.inf毫不费力地分配。但现在任何其他浮动也被接受。
有没有办法正确限制类型提示?或者我type: ignore每次分配无穷大时都被迫使用?
int该类可以通过子类化来扩展,而不是添加特定值。这种方法并非没有许多陷阱和挑战,例如需要处理各种__dunder__方法的无穷大值(即__add__,__mul__,__eq__等等,并且所有这些都应该进行测试)。在需要特定值的用例中,这将是不可接受的开销。在这种情况下,用 包装所需值typing.cast将能够更好地向类型提示系统指示inf = cast(int, math.inf)可以接受分配的特定值(即 )。
这种方法不正确的原因很简单:由于分配的值看起来/感觉起来与某个数字完全相同,因此您的 API 的其他一些用户可能最终会无意中将其用作 an ,int然后程序可能会在他们身上严重爆炸math.inf(或变体)提供此类)。
一个类比是这样的:鉴于列表具有由正整数索引的项目,我们期望任何返回某个项目的索引的函数都是某个正整数,因此我们可以直接使用它(我知道Python中不是这种情况)假设存在允许使用负索引值的语义,但假设我们目前正在使用 C)。假设此函数返回匹配项的第一次出现,但如果有任何错误,它会返回一些负数,这显然超出了某些项索引的有效值范围。缺乏对返回值的天真的使用的防范将不可避免地导致类型系统应该解决的问题。
本质上,创建代理值并将其标记为int将提供零值,并且不可避免地允许程序由于自动允许的不正确使用而表现出意外和损坏的 API/行为。
更不用说无穷大不是一个数字,因此没有任何int值可以正确地表示它(假设int它本质上代表了一些有限的数字)。
顺便说一句,看看str.indexvs str.find。其中之一的返回值肯定违反了用户的期望(即超出了正整数类型的边界;不会被告知返回值对于编译时可能使用的上下文可能无效,导致运行时随机出现潜在故障)。
考虑到问题实际上是关于当存在速率时对某个整数的分配,如果不存在,则应该完成一些代表特定用例无界性的其他标记(它可能是一些内置值,例如 或NotImplemented)None。然而,由于这些标记也不是int值,这意味着myvar实际上需要一个包含这些标记的类型,并且需要一种应用执行正确操作的操作的方法。
不幸的是,这在Python中不能以非常好的方式直接使用,但是在像Haskell这样的强静态类型语言中,更容易接受的解决方案是使用类型Maybe来定义可以接受无穷大的数字类型。请注意,虽然浮点无穷大也可用,但它继承了浮点数的所有问题,这使得它成为一个站不住脚的解决方案(再次强调,不要用于inf此目的)。
回到Python:根据您实际想要的赋值的属性,它可以像创建一个带有可以接受 or (int或None)的构造函数的类一样简单NotImplemented,然后提供该类的用户可以创建的方法使用实际值。不幸的是,Python 没有提供高级构造来使其变得优雅,因此您将不可避免地最终得到管理此问题的代码散布在各处,或者必须编写许多方法来按预期处理任何输入并在中生成所需的输出。你的程序实际需要的具体方式。
不幸的是,类型提示实际上只是触及了表面,只是简单地覆盖了更高级的语言在更基础的层面上提供和解决的问题。我想如果一个人必须用 Python 编程,那总比没有好。
| 归档时间: |
|
| 查看次数: |
1499 次 |
| 最近记录: |