What's the correct way to type hint an empty list as a literal in python?

huangapple go评论426阅读模式
英文:

What's the correct way to type hint an empty list as a literal in python?

问题

我有一个总是返回空列表的函数(为什么是空列表是一个很长的故事),我可以像通常一样使用"type hint"来指定返回类型为"list",但是指示列表始终相同会更有用。

我最初的想法是使用字面量,像这样:

from typing import Literal

def get_empty_list() -> Literal[[]]:
    return []

Mypy将其标记为无效类型,有没有一种正确的方法来指定始终为空的列表的类型提示?(显然,我可以只用"list"来指定类型,但这不够有帮助)

明确一点,这是一个始终为空且不希望有任何元素的列表(与当前为空但可能在以后添加某种类型的元素的列表相分离)。

英文:

I have a function that always returns an empty list (it's a long story why), I could type hint as usual with just "list", but it would be useful to indicate that the list is always going to be the same.

My first thought was to use literal like this:

from typing import Literal

def get_empty_list() -> Literal[[]]:
    return []

Mypy flags this as an invalid type, is there a correct way to type hint an always empty list? (obviously, I could type hint just a list, but this is less helpful)

To be explicit, this is a list that is always empty and doesn't expect to have any elements. (As seperate for example, from a list that is currently empty, but might have elements of some type added later on).

答案1

得分: 4

如果你想要表示“列表当前没有元素,但可能会在以后添加元素”的类型,那么这基本上不是一个静态类型。向这样的列表添加元素是有效的,但会导致列表不再是该类型的元素,这在遵守静态类型的程序中是不应该发生的。

如果你想要表示“列表没有元素,并且将永远不会有元素”的类型,你可以这样做:

from typing import Never

def get_empty_list() -> list[Never]:
    return []

在这里,我们将元素类型注释为typing.Never,这是一个没有值的类型。实际上,这是mypy为一个空列表字面量推断出的类型,如果没有上下文来暗示其他类型,可以通过reveal_type看到:

from typing import Never

x: list[Never]
reveal_type(x)
reveal_type([])

mypy输出:

main.py:4: note: Revealed type is "builtins.list[<nothing>]"
main.py:5: note: Revealed type is "builtins.list[<nothing>]"
Success: no issues found in 1 source file

使用list[Never]类型的影响如下:

  • 静态类型检查器不允许对注释为list[Never]的列表进行添加元素的操作。

  • 它们将允许像get_empty_list().append(sys.exit())这样的操作,其中append的参数是一个无法求值的表达式。

  • 它们将认识到get_empty_list()[0]无法求值为一个值... 但这与将其视为被禁止的操作非常不同。实际上,它们会在几乎任何上下文中允许它。
    毕竟,如果一个表达式无法产生一个值,那么它无论是什么正确的类型,都无法产生一个错误类型的值。所以你可以做像这样的事情:

    x: int = get_empty_list()[0]
    

    从静态类型的角度来看,这是完全有效的。([][0]也被认为是有效的。)

  • 它们将不会认识到len(get_empty_list())必须为0。

英文:

If you want a type that expresses "list that doesn't have elements now, but might have elements added later", then that's fundamentally not a static type. Appending elements to such a list would be valid, but would cause the list to stop being an element of that type, which should not happen with static types in a program that respects static typing.

If you want something that expresses "list that has no elements, and will never have elements", you can kind of do it:

from typing import Never

def get_empty_list() -&gt; list[Never]:
    return []

Here, we've annotated the element type as typing.Never, a type with no values. This is actually the type mypy infers for an empty list literal if there's no context to suggest another type, as you can see with reveal_type:

from typing import Never

x: list[Never]
reveal_type(x)
reveal_type([])

mypy output:

main.py:4: note: Revealed type is &quot;builtins.list[&lt;nothing&gt;]&quot;
main.py:5: note: Revealed type is &quot;builtins.list[&lt;nothing&gt;]&quot;
Success: no issues found in 1 source file

Here are the implications of using a list[Never] type:

  • Static type checkers will not allow operations that add elements to a list annotated as list[Never].

  • They will allow operations like get_empty_list().append(sys.exit()), where the argument to append is an expression that cannot evaluate to a value.

  • They will recognize that get_empty_list()[0] cannot evaluate to a value... but this is very different from considering it a prohibited operation. In fact, rather than prohibiting the operation, they will allow it, in almost any context.

    After all, if an expression cannot produce a value, then it cannot produce a value of the wrong type, no matter what the right type is. So you can do stuff like

    x: int = get_empty_list()[0]
    

    and from a static typing perspective, that's perfectly valid. ([][0] is considered valid too.)

  • They will not recognize that len(get_empty_list()) must be 0.

答案2

得分: -3

from typing import List

def get_empty_list() -> List:
    return []

result = get_empty_list()
print(result)  # 输出: []

没有任何类型参数的List注释用于指示函数返回一个列表,但它没有指定列表中元素的类型。

英文:
from typing import List

def get_empty_list() -&gt; List:
    return []

result = get_empty_list()
print(result)  # Output: []

The List annotation without any type parameters is used to indicate that the function returns a list, but it doesn't specify the type of elements in the list.

huangapple
  • 本文由 发表于 2023年8月11日 15:26:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76881483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定