【问题标题】:checking type of range in python's typing module检查python类型模块中的范围类型
【发布时间】:2019-07-06 00:44:24
【问题描述】:

这是关于缺少typing.Range

typing包中没有range的类型,但同时我们看到typing.re.Match,这是一个面向包的类型。 typing.sequencetyping.Iterable 太宽泛了。

有没有更好的方法来检查range 类型并且只检查range 类型?除了使用:

range_instance.__class__ == range

更新

明确地说,我的意思是打字中的某些类型包括某物的所有元素或方面,例如typeing.Iterable(通用类型,这很好)

另一方面,也有非常特定的类型,如

typing.Generator, typing.Tuple, typing.Dict, typing.re.Match typing.AsyncContextManager, ...

但不是

typing.Range

事实 1:range 类型是 python 中的不同类型 (例如,一个范围有额外的优化用于检查那里的元素,有时知道你是在处理列表还是范围是有意义的)

事实 2:typing 模块似乎涵盖了类型的所有方面。 (如果您有疑问,请参阅那里的导入和逻辑)

知道这一点,我认为typing.Range 不见了。

否则,人们对使用哪一个感到困惑:

r: ranger: typing.Iterable 或创建自定义别名

类型提示和类型检查之间的区别在这里并不重要。

【问题讨论】:

  • isinstance(range_instance, range) 有什么问题吗?
  • 您混淆了两个相似但不同的东西:类型化模块为类型注释提供了泛型类型,用于文档和提示ing。另一方面,类型检查是可靠的检查对象是从定义的类或父类派生的。它在某些用例中可能是有效的,但它通常反对 Python 的鸭子类型概念。
  • @Klaus:不,我不这样做,因为typing 不仅服务于泛型类型,而且由于该模块基于typescollectionsabc 等,所以有使用该包不仅可以用于类型提示,还可以用于类型检查。当然,我们不限于使用该模块进行类型检查。也许这根本不应该是第一次尝试。

标签: python python-3.x type-hinting


【解决方案1】:

而不是(不可能,因为 typing.Range 不存在):

from typing import Range
    
def foo(r: Range) -> None:
    ...

只要做:

def foo(r: range) -> None:
    ...

由于range 既是一个类型又是一个工厂函数,因此您不需要为范围使用单独的类型。

请注意,存在诸如 typing.Dict 之类的类型,因为虽然 dict 已经是一种类型,但以前不支持将内置类型用作泛型,因此您不能将 dict[str, int] 用作类型注释,必须做 Dict[str, int]。但由于range 在逻辑上不是泛型,因此不需要在typing 中对应于range 的单独类型来支持泛型。

【讨论】:

  • 那么使用哪一个? r: ranger: typing.Iterable?
【解决方案2】:

typinginterface segregation 的主要思想。在大多数情况下,您不应该关心传递的参数是否实际上是 range 对象,而是关心其功能的某些方面。在大多数情况下,typing.Iterable 涵盖了该功能(我不明白您所说的“太全面”是什么意思)。

另一方面,如果你想明确检查范围类型,只需使用isinstance(x, range)

【讨论】:

  • 我已经更新了上面的问题,谢谢你的链接。我认为由于没有提供typing.Range,ISP 在输入范围的模块中被破坏了。
  • @SławomirLenart 为什么您希望typing.Range 存在? range 既不是接口(如typing.Iterable)也不是泛型(如typing.List); typing.Range 绝对没有理由成为一件事。这实际上与range 相同。
  • @SławomirLenart:我认为恰恰相反。 range 对于大多数用途来说只是一个可迭代的。所以,你应该被iterable覆盖。但是,您是对的,typing 模块在它所代表的方面有点不一致。请记住,尽管这是事后的想法,而且它相对较新。另一方面,abc.collections 更清楚地遵循接口隔离
【解决方案3】:

你问:

有没有更好的方法来检查range类型和只有range类型,此外:

range_instance.__class__ == range

我认为您可以在这种情况下使用isinstance()(我在Python 3.x 中测试过):

>>> isinstance(range(10), range)
True
>>> isinstance(list(range(10)), range)               # this is a list
False
>>> isinstance([1, 2, 3, 4], range)                  # this is a list
False
>>> isinstance((e for e in range(10)), range)        # this is a generator
False

如您所见,它可以正确识别范围对象,并且不会被列表或生成器混淆。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多