3

我有以下功能:

from lxml import etree
from typing import Union


def _get_inner_xml(element: Union[etree._Element, None]) -> Union[str, None]:
    if element is None:
        return None
        
    # See https://stackoverflow.com/a/51124963
    return (str(element.text or "") + "".join(etree.tostring(child, encoding="unicode") for child in element)).strip()


root = etree.fromstring('<html><body>TEXT<br/>TAIL</body></html>')
innerXML = _get_inner_xml(root)
print(innerXML)

我对它的理解是,如果我None作为参数传递,我总是得到None作为返回值。另一方面,etree._Elementas 参数总是会导致str返回。

如果我使用 pylance 在 vscode 中编写以下内容(它在后台使用 pyright):

def test(element: etree._Element):
    variable = _get_inner_xml(element)

在这种情况下,我得到类型提示(variable) variable: str | None。我希望 pylance 知道该变量应该是 type str。我在监督什么吗?这可能是一个错误吗?

如果这按预期工作:是否有可能手动告诉 pylance“只要这个函数得到 aetree._Element它就会返回 astr并且每当我通过None它时它就会返回None”?

4

2 回答 2

2

这里的答案是使用typing.overload此处的文档),它允许您为一个函数注册多个不同的签名。用修饰的函数定义@overload在运行时被忽略——它们只是用于类型检查器——所以函数的主体可以用文字省略号填充...pass或者只是一个文档字符串。您还需要确保提供不使用@overload.

from lxml import etree
from typing import Union, overload

@overload
def _get_inner_xml(element: etree._Element) -> str: 
    """Signature when `element` is of type `etree._Element`"""

@overload
def _get_inner_xml(element: None) -> None: ...
    """Signature when `element` is of type `None`"""

def _get_inner_xml(element: Union[etree._Element, None]) -> Union[str, None]:
    if element is None:
        return None
        
    # See https://stackoverflow.com/a/51124963
    return (str(element.text or "") + "".join(etree.tostring(child, encoding="unicode") for child in element)).strip()


root = etree.fromstring('<html><body>TEXT<br/>TAIL</body></html>')
innerXML = _get_inner_xml(root)
print(innerXML)
于 2021-08-12T13:04:52.433 回答
0

这不是类型提示的工作方式。要知道在 IDE 中输入 alwaysetree._Element会导致 returnetree._ElementNonealways 结果输入,None需要解析函数,分析所有路径并获得该结果。

我非常怀疑它是否可以做到这一点。相反,IDE 只是解析签名中的注释并将它们作为提示返回 - 类型提示就是这样 - 它们不会在代码执行时强制执行。

您可能需要使用更简单的功能进行检查:

# this will either return a None or a str - it simply returns what is inputted
def test(element: Union[str, None]) -> Union[str, None]:
    return element


should_be_str = test("should be a str as type hint return")
should_be_none = test(None) 

should_be_marked_as_type_mismatch = test(42) # works from the signature information

看看你的IDE是否选择了那个——我严重怀疑。

于 2021-08-12T09:33:22.250 回答