注释参数以允许可以反转的列表的正确方法是什么?
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]
我们应该包括这两种类型吗?有更好的方法来注释吗?
def foo(l: list[int] | reversed[int]) -> None:
...
编辑:我试图保持
foo
通用,但有人指出 l
在函数中的使用方式对问题很重要。保持问题相对抽象,l
需要能够利用所有典型的list
方法(append
、extend
、remove
、insert
等)
注释可反转列表的正确方法是什么? [...] l 需要能够利用所有典型的列表方法(追加、扩展、删除、插入等)
常规列表注释可以很好地表示具有列表所有功能的对象。这包括可逆性。但是,您必须传递一个列表才能使其发挥作用。对
reversed
的调用可能不会返回 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
另一方面。内置行为通常有与之关联的 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