您好,我正在尝试使用
types-lxml
库输入提示lxml返回类型。
def parse_xml(path: str) -> etree._ElementTree:
return etree.parse(path)
def components(path: str) -> List[etree._Element]:
return parse_xml(path).xpath("/node1/node2")
但是mypy抱怨第二个函数说:
error: Returning Any from function declared to return "List[_Element]" [no-any-return]
知道如何解决这个问题吗?谢谢。
看起来遇到了
lxml
和
mypy
的常见问题。尽管
types-lxml
提供了一些类型提示,但
lxml
的
xpath
方法的返回类型并不总是准确推断出来的。
以下是一些解决方法:
1. 类型断言:
这是最简单粗暴的方法,可以直接告诉
mypy
知道
xpath
返回的是
List[etree._Element]
:
from typing import List
from lxml import etree
def parse_xml(path: str) -> etree._ElementTree:
return etree.parse(path)
def components(path: str) -> List[etree._Element]:
result = parse_xml(path).xpath("/node1/node2")
assert isinstance(result, list) # 确保 result 是列表
return result # type: ignore[return-value]
type: ignore[return-value]
告诉
mypy
忽略该行代码的类型检查。
2. 使用类型守卫:
可以创建一个函数来检查返回值的类型,并将其作为类型守卫使用:
from typing import List, TypeVar
from lxml import etree
T = TypeVar('T')
def is_element_list(value: object) -> value is List[etree._Element]:
return isinstance(value, list) and all(isinstance(item, etree._Element) for item in value)
def parse_xml(path: str) -> etree._ElementTree:
return etree.parse(path)
def components(path: str) -> List[etree._Element]:
result = parse_xml(path).xpath("/node1/node2")
if is_element_list(result):
return result
else:
raise TypeError("xpath did not return a list of _Element")
3. 自定义类型提示:
可以为
xpath
创建更精确的类型提示,但这需要深入了解
lxml
的内部机制:
from typing import List, overload, TypeVar
from lxml import etree
_T = TypeVar('_T')
class _ElementTree(etree._ElementTree):
@overload
def xpath(self, _path: str, **_kwargs: object) -> List[etree._Element]: ...
@overload
def xpath(self, _path: str, **_kwargs: object) -> List[_T]: ...
def parse_xml(path: str) -> _ElementTree:
return etree.parse(path) # type: ignore[return-value]
def components(path: str) -> List[etree._Element]:
return parse_xml(path).xpath("/node1/node2")
选择哪种方法取决于的具体情况和个人偏好。
标签:python,lxml,mypy From: 78841928