我正在使用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]
但是mypy
不喜欢这样,因为它抱怨:
$ mypy urltest.py
"URL" has no attribute "_val"
那么,我如何在自己的项目中“附加”(或扩展)实例属性注释到URL
上,以便可以在项目的其余部分中使用它?即
from yarl import URL
URL._val: SplitResult
# ...
(mypy也不喜欢;“无法在分配给非self属性时声明类型。”)
我尝试在stubs/yarl/__init__.pyi
中创建一个新的存根文件:
from urllib.parse import SplitResult
class URL:
_val: SplitResult
然后按照stub files中所述设置export MYPYPATH='.../stubs'
。但是,此会覆盖而不是扩展现有的注释,因此所有但 ._val
都会抛出错误:
错误:“ URL”没有属性“ with_scheme”
错误:“ URL”没有属性“主机”
错误:“ URL”没有属性“片段”
...等等。
答案 0 :(得分:1)
一种可能性是简单地忽略此分配的u
类型:
def foo(u: URL) -> Tuple[str, str, str, str]:
sr: SplitResult = typing.cast(typing.Any, u)._val
return sr[:3]
mypy
将假定您知道自己在做什么,并且u
具有类型为_val
的{{1}}属性。
答案 1 :(得分:1)
不幸的是,我认为没有真正的方法可以对某些第三方库的类型提示进行“部分”更改-至少不是mypy。
我会尝试以下三个选项之一:
只需# type: ignore
属性访问权限即可:
def foo(u: URL) -> Tuple[str, str, str]:
sr: SplitResult = u._val # type: ignore
return sr[:3]
此类型忽略将禁止在该行上生成的任何错误消息。如果您要采用这种方法,我还建议您使用--warn-unused-ignores
标志运行mypy,该标志将报告任何冗余和未使用的# type: ignore
语句。这个特定的# type: ignore
不太可能随着mypy更新/作为第三方库存根的更新而变得多余,但这是一个很好的标记,可以启用它。
与该库的维护者交谈,看看他们是否愿意为此属性添加类型提示(即使它是私有的),还是愿意通过一些新的API公开此信息。
如果有帮助,就有 先例,即使在Typeshed(标准库的类型存储库)中,也可以为私有或未记录的属性添加类型提示-请参见"What to include" section in their contribution guidelines。 / p>
如果库维护者不愿意添加此属性,则始终可以只为该库创建存根,对派生的存根进行更改,然后开始使用它。
我个人将首先尝试解决方案2,然后再尝试解决方案1,但这就是我自己。