注释可反转列表的正确方法是什么?

Acu*_*fQA 5 python type-hinting python-3.x mypy

注释参数以允许可以反转的列表的正确方法是什么?

mylist = [1,2,3,4,5]
flipped = reversed(mylist)


def foo(l: list[int]) -> None:
    # assuming `l` is list object which can utilize any of it's methods.
    l.append(123)
    return

foo(mylist)
foo(flipped). # error: Argument 1 to "foo" has incompatible type "reversed[int]"; expected "list[int]"  [arg-type]
Run Code Online (Sandbox Code Playgroud)

我们应该包括这两种类型吗?有没有更好的方法来注释这个?

def foo(l: list[int] | reversed[int]) -> None:
   ...
Run Code Online (Sandbox Code Playgroud)

编辑:我试图保持foo通用,但有人指出l函数中的使用方式对问题很重要。保持问题相对抽象,l需要能够利用所有典型list方法(appendextendremoveinsert等)

小智 2

注释可反转列表的正确方法是什么?[...] l 需要能够利用所有典型的列表方法(追加、扩展、删除、插入等)

常规列表注释可以很好地表示具有列表所有功能的对象。这包括可逆性。但是,您必须传递一个列表才能使其发挥作用。调用reversed可能不会返回 a list,具体取决于您正在运行的 python 。

mylist = [1, 2, 3, 4, 5]
flipped = list(reversed(mylist))  # type remains a list

def foo(l: list[int]) -> None:
    l.append(123)
    l[:] = list(reversed(l))

foo(mylist)  # fine
foo(flipped)  # also fine
Run Code Online (Sandbox Code Playgroud)

另一个注意事项。内置行为通常有与之关联的dunder方法。例如,可逆性具有__reversed__。如果您需要为实现特定行为/方法的对象指定类型提示,则可以使用该类来完成Protocol

from typing import Protocol, runtime_checkable, Any

@runtime_checkable
class Reversible(Protocol):
    def __reversed__(self) -> list[Any]:
        ...

def foo(l: Reversible) -> None:
    l.append(123)

    assert isinstance(l, Reversible)  # will it work?
    l[:] = list(reversed(l))

foo(mylist)  # all good
Run Code Online (Sandbox Code Playgroud)

  • [`collections.abc.Reversible`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Reversible) 已经存在,所以你可以使用它。 (4认同)