繁体   English   中英

类型提示,其中一个参数是另一个参数的类型

[英]Type hint where one argument is the type of another

我无法为一对参数表达精确的类型提示,其中一个参数需要是某个类型的实例的值,另一个需要是类型本身或某个超类型。

在 Python 中看到这种情况的一种情况是在上下文管理器(类)的__exit__方法中。

import typing as t
from types import TracebackType
from contextlib import AbstractContextManager

class Acme(AbstractContextManager):
  def __exit__(self, exc_type: t.Type[Exception], exc: Exception,
      tb: Tracebacktype) -> None:
    ...

这种特定情况可能无关紧要,因为上下文管理器由 Python 在内部处理,但我仍然想了解如何表达两个 arguments,其中第一个是第二个的(超)类型。

从概念上讲,我的问题是我想表达值exc_type exc某个子类型。 在上面的表达式中,我猜 mypy 会对 arguments 像LookupError, RuntimeError('foo')非常满意,即使RuntimeError不是LookupError的类型。 有没有更好的方法来表达这一点,mypy 会发现这种错误?

更新

在这里使用 TypeVars 尝试一个测试用例:

import typing as t

C = t.TypeVar('C', bound=t.Collection)

def f(t: t.Type[C], c: C) -> None:
  pass

f(t.Dict, [])

我希望 mypy 抱怨这段代码,因为即使空列表是一种集合,它也不是字典。

这种对Type[some_type_var]的使用似乎不鼓励PEP中的一个部分,其中只提供了这种支持的一个子集(特别是用于将TypeVar绑定到 class 类型)。 看来这种劝阻不是哲学上的(这将是 generics 在类型和值都是一流的语言中的常见用法) - 但与类型检查器的实际实现更相关。 TypeVar用于类方法签名(您问题的一个特例)甚至是对 pep 的后期添加


不适用于 mypy 的可能解决方案(截至目前)

标准TypeVar

Type[some_type_var]的 function 签名中没有类型检查。 这不是基于some_type_varcontravariant还是covariant的变量(也不应该是)。

TypeVarType[TypeVar]

T = TypeVar("T")
Meta = TypeVar("Meta", bound=Type[T])

def foo(the_type: Meta, the_value: T):
   ....

TMeta不能“绑定”在一起。


令我惊讶的是,在某些情况下,您可以排除一些这种行为(但这是一种特殊情况,这对我来说似乎未定义)

T = TypeVar('T', str, int, float, bytes)

class Foo:

    def bar(self, the_type: Type[T], the_value: T):
        print(isinstance(the_value, the_type))

f = Foo()
f.bar(str, "baz")
f.bar(str, b"baz")  # wrong!
f.bar(int, 1)
f.bar(int, 3.15159)  # wrong! (but no complaint)
f.bar(float, 1.0)
f.bar(float, 1)  # wrong! (but no complaint)
f.bar(float, b'1.0')  # wrong!

给予

so.py:nn: error: Value of type variable "T" of "bar" of "Foo" cannot be "object"
so.py:nn: error: Value of type variable "T" of "bar" of "Foo" cannot be "object"
Found 2 errors in 1 file (checked 1 source file)

但似乎只适用于 python 的原始类型(这不适用于用户空间类型)(同样,只有一些python 的原始类型如图所示(参见floatint错误错过)。我认为这是一个明确的“不错-to-have” TypeVar的扩展(并使更多Generic用例成为可能)。


mypy上有一些相关的问题:

  1. 关于 class 注释行为
  2. TypeVarTypeVar

这就是TypeVar的用途:你想要这样的东西:

from types import TracebackType
from typing import Type, TypeVar
from contextlib import AbstractContextManager

_E = TypeVar('_E', bound=Exception)

class Acme(AbstractContextManager):
    def __exit__(
        self,
        exc_type: Type[_E],
        exc: _E,
        tb: Tracebacktype
    ) -> None:
    ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM