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 betweenstr
and Sequence[str]
/Iterable[str]
(不幸的是这不太可能)。
【参考方案1】:
PEP 484 不包括指定“列入黑名单”类型的内置方式。
做这种事情通常没有什么意义——我能想到你为什么想做这样的事情的唯一原因是如果你想区分str
和Iterable[str]
或@987654324 @以某种方式。如果是这种情况,不幸的是 PEP 484 doesn't have a way of letting you do this -- str,无论好坏,都是这两种类型的合法子类。
在这种情况下,最好的办法是修改类型签名以区分str
和List[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 插件系统是一个未记录、暂定且极易更改的功能,但如果您真的想这样做,可能需要调查一下。
如果您特别想区分 str
和 Sequence[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 类型提示 -> 返回类型是类名还是无?