如何使用注释返回多个值?

4

我最近发现了Python 3.x中的函数注释以及它们可能具有的用处。

我安装了typeannotations模块,以便对参数和返回类型进行类型检查。

工作示例:

from annotation.typed import typechecked    

@typechecked
def test_func(arg1: int) -> int:
    return arg1   

print(test_func(1))

>>> 1

以下是一个错误的示例,会引发TypeError异常。

from annotation.typed import typechecked

@typechecked
def test_func(arg1: int) -> str:
    return arg1   

print(test_func(1))

>>>TypeError: Incorrect return type

然而我还没有能够弄清楚如何使用 typechecker 来返回多个值

from annotation.typed import typechecked

@typechecked
def test_func(arg1: str, arg2: str) -> (str, str):
    return arg1, arg2

print(test_func('hello', 'world'))

我传入了两个str并返回一个包含两个str的列表,但是它引发了异常。
TypeError: Incorrect return type

我该如何以这种方式返回多个值?

不错的问题。你能否检查一下 -> tuple: 是否起作用? - Bhargav Rao
@BhargavRao,元组可以工作,但我不确定OP是否想更具体,或者您是否实际上可以。 - Padraic Cunningham
据我所知,类型提示(Pep483)没有提到关于嵌套返回值的问题。因此,我猜测 OP 需要进行一些客户端类型检查。 - Bhargav Rao
1个回答

1
短答案是“不”。 长答案是“是”,但需要进行一些编程: 如果您习惯于修改源代码(我曾多次这样做),则可以实现自己的方法来完成此操作。 请记住,这只是一个快速的代码示例,我相信有更有效的方法来完成此操作,但这将为您提供所需的内容: 在“typed.py”文件中,找到“_check_return_type()”函数,并将其更改为以下内容:
def _check_return_type(signature, return_value):
    """Check that the return value of a function matches the signature."""
    annotation = signature.return_annotation

    if annotation is EMPTY_ANNOTATION:
        annotation = AnyType

    # If the return type is a tuple of typed values, and the length is greater than 1 (to prevent the actual tuple return type)
    if isinstance(annotation, tuple) and len(annotation) > 1:
        for p, a in zip(return_value, annotation):
            if not isinstance(p, a):
                raise TypeError('Incorrect return type: {} ({} required)'.format(type(p), a))

    else:
        if not isinstance(return_value, annotation):
            raise TypeError('Incorrect return type')
    return return_value

这将按照您设置的元组顺序检查返回的每个值。
现在,如果您不想修改原始源代码,可以编写自己的函数并像这样调用它:
def typechecked(target):
    import inspect
    import functools

    @functools.wraps(target)
    def wrapper(*args, **kwargs):
        signature = inspect.signature(target)
        params = target(*args, **kwargs)

        for p, a in zip(params, signature.return_annotation):
            if not isinstance(p, a):
                raise TypeError('Incorrect return type: {} ({} required)'.format(type(p), a))
        return params

    return wrapper

希望这有所帮助。

这个解决方案很好,谢谢!我宁愿写更多的代码也不想修改源代码。但是如果没有给出返回类型,这将会出现问题,但我并不认为我会遇到没有返回类型的情况。 - Wondercricket
1
只有在必要的情况下才会修改核心代码。有时候确实需要,但如果有解决方法,我会全力支持它。 - CodeLikeBeaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接