Bra*_*mon 11 python python-3.x mypy
我正在使用yarl图书馆的URL对象。
它有一个准私有属性 ,._val它是一个urllib.parse.SplitResult对象,但在 中没有类型注释yarl/__init__.pyi。(如果开发人员不想正式将其纳入公共 API,这是可以理解的。)
但是,我选择使用URL._val,风险自负。一个虚拟示例:
# urltest.py
from urllib.parse import SplitResult
from typing import Tuple
from yarl import URL
def foo(u: URL) -> Tuple[str, str, str]:
sr: SplitResult = u._val
return sr[:3]
Run Code Online (Sandbox Code Playgroud)
但mypy不喜欢这个,因为它抱怨:
$ mypy urltest.py
"URL" has no attribute "_val"
Run Code Online (Sandbox Code Playgroud)
那么,在我自己的项目中,我如何“附加”(或扩展)实例属性注释,以便URL它可以在我的项目的其余部分中使用?IE
from yarl import URL
URL._val: SplitResult
# ...
Run Code Online (Sandbox Code Playgroud)
(mypy 也不喜欢这样;“不能在对非 self 属性的赋值中声明类型。”)
我尝试在以下位置创建一个新的存根文件stubs/yarl/__init__.pyi:
from urllib.parse import SplitResult
class URL:
_val: SplitResult
Run Code Online (Sandbox Code Playgroud)
然后按照存根文件export MYPYPATH='.../stubs'中的描述进行设置。然而,这会覆盖而不是扩展现有的注释,因此除了抛出和错误之外的所有内容: ._val
错误:“URL”没有属性“with_scheme”
错误:“URL”没有属性“主机”
错误:“URL”没有属性“片段”
...等等。
不幸的是,我认为确实没有办法对某些第 3 方库的类型提示进行“部分”更改 - 至少不能使用 mypy。
我会尝试以下三个选项之一:
只是# type: ignore属性访问:
def foo(u: URL) -> Tuple[str, str, str]:
sr: SplitResult = u._val # type: ignore
return sr[:3]
Run Code Online (Sandbox Code Playgroud)
此类型忽略将抑制该行上生成的任何错误消息。如果您打算采用这种方法,我还建议使用该--warn-unused-ignores标志运行 mypy,它将报告任何冗余和未使用的# type: ignore语句。# type: ignore当 mypy 更新/作为第三方库更新的存根时,这个特殊功能不太可能变得多余,但它是一个很好的标志,可以在一般情况下启用。
与该库的维护者交谈,看看他们是否愿意为此属性添加类型提示(即使它是私有的),或者通过一些新的 API 公开该信息。
如果有帮助的话,即使对于标准库的类型存储库 Typeshed 中的私有或未记录的属性,也有一些添加类型提示的先例 - 请参阅其贡献指南中的“包含内容”部分。
如果库维护者不愿意添加此属性,您始终可以分叉此库的存根,对分叉的存根进行更改,然后开始使用它。
我个人会先尝试解决方案 2,然后再尝试解决方案 1,但这只是我的想法。