PEP 484:类型提示的专有类型

Posted

技术标签:

【中文标题】PEP 484:类型提示的专有类型【英文标题】:PEP 484: exclusive type for type hint 【发布时间】:2018-03-01 00:45:55 【问题描述】:

我可以指定独占类型吗?像这样的:

def foo(bar: Not[str]) -> None:
    assert not isinstance(bar, str)
    print(type(bar))

【问题讨论】:

你的意思是一个可以表示任何东西的注释,而不是字符串?我认为这不是很有用,所以我怀疑它是可能的。 您的函数可能会做什么以使任何除了字符串都可用? @chepner -- 不知道 OP 想要做什么,但我能想到的一件事是尝试distinguish between str and Sequence[str]/Iterable[str](不幸的是这不太可能)。 【参考方案1】:

PEP 484 不包括指定“列入黑名单”类型的内置方式。

做这种事情通常没有什么意义——我能想到你为什么想做这样的事情的唯一原因是如果你想区分strIterable[str]或@987654324 @以某种方式。如果是这种情况,不幸的是 PEP 484 doesn't have a way of letting you do this -- str,无论好坏,都是这两种类型的合法子类。

在这种情况下,最好的办法是修改类型签名以区分strList[str],这 合法可区分的类。不理想,但总比没有好。


也就是说,如果你真的想做这样的事情,那是有可能的,假设你使用的是 mypy 并且不介意诉诸肮脏的黑客。

一个技巧是基本上修改您的foo 函数,使其始终返回某些内容并滥用overload 和非严格可选模式的语义,如下所示:

from typing import overload, Optional

@overload
def foo(bar: str) -> None: ...

# Alternatively, replace "object" below
# with the types you *do* want to allow

@overload
def foo(bar: object) -> int: ...

def foo(bar: object) -> Optional[int]:
    assert not isinstance(bar, str)
    print(type(bar))
    return 0

def main() -> None:
    x = 0

    x = foo(3)       # typechecks
    x = foo("foo")   # fails

如果您尝试在没有--strict-optional 标记的情况下在 mypy 中运行它,mypy 将使用 "foo" does not return a value 错误标记最后一行。然后,您需要记住出现此错误消息是因为您传入了一个字符串参数。您还需要记住始终将 foo 函数的输出分配给一个值。

(如果你启用了严格可选,mypy 会抱怨你的两个重载有不兼容的签名。)

我们在这里基本上做的是:

    利用禁用严格可选的事实,None 是每种类型的合法值(因此重载是合法的) 利用 mypy 会(作为一项额外功能)警告您从不返回任何内容的函数中分配值的情况。

这一切都很老套,很可能是个坏主意。我也不承诺这种互动将在未来继续发挥作用。


您可以尝试的第二个技巧是编写一个 mypy 插件来捕获特定案例的实例。在撰写本文时,mypy 插件系统是一个未记录、暂定且极易更改的功能,但如果您真的想这样做,可能需要调查一下。


如果您特别想区分 strSequence[str]Iterable[str](或类似的东西),您可以尝试的其他方法是:

    创建 Typeshed 和/或打字模块的自定义分支 修改str 的类定义/存根,使其不继承自Sequence[str]Iterable[str](或添加幻像类型或其他内容) 通过--custom-typeshed-dir--custom-typing 命令行参数使mypy 使用您的自定义类型定义。

基本上,如果默认类型层次结构不是您想要的,请发明一个自定义层次结构。


当然,如果您正在使用其他一些符合 PEP 484 的检查器(例如 Pycharm 的内置检查器),那么您可能不走运。

【讨论】:

以上是关于PEP 484:类型提示的专有类型的主要内容,如果未能解决你的问题,请参考以下文章

PEP 484 类型提示 -- Python官方文档译文 [原创]

numpy.ndarray 的类型提示/注释 (PEP 484)

Python PEP 484 类型提示 -> 返回类型是类名还是无?

如何在 PEP484 之后的方法参数中设置与类相同的类型? [复制]

PEP-484 具有自己类型的类型注释

我应该如何使用 Optional 类型提示?