指示参数应该是可变引用

Indicating that a parameter should be a mutable reference

使用 PEP 484 和 585 中指定的类型提示语法,是否有任何方法可以指示函数的参数应该是一个可以被函数修改的可变引用?

例如,C# 有 ref 个参数,所以在 Python 中是否有等效参数?例如

>>> def foo(spam: "Mutable[List[int]]"):
...     spam.append(sum(spam))
...
>>> a = [1, 2, 3]
>>> foo(a)
>>> a
[1, 2, 3, 6]

或者如果不是,我如何定义这样的类型而不导致检查逻辑认为它是特殊的 Mutable class 而不是 List[int]?显然,这将用作开发人员更容易理解方法的工具,而不是用于从根本上改变程序的工具。

为清楚起见,我知道列表根据定义是可变的,但我想知道是否有一种方法可以定义何时它会发生变异,例如

>>> def bar(sandwich: Mutable[List[str]], fridge: List[str]):
...     sandwich.extend(random.sample(fridge, k=3))

列表在 Python 中是可变的,因此不需要明确的 Mutable class 引用:

In [3]: from typing import List

In [7]: def foo(spam:List[int]):
   ...:     spam.append(sum(spam))
   ...:     return spam  

In [8]: a = [1,2,3]   

In [9]: foo(a)

Out[9]: [1, 2, 3, 6]

默认情况下,列表被认为始终是可变的。因此,如果您想指示某个列表永远不会更改,最好使用一些只读接口或协议(例如 typing.Sequencetyping.Collection 来明确指示。

这两种类型与相应的 collections.abc 类型具有相同的语义。我想您可以认为它们与 C# 的 IReadOnlyCollection 大致相同。

from typing import Sequence, overload

def foo(seq: Sequence[int]) -> None:
    # This type checks
    for item in seq:
        print(seq)

    # ...but this does not. Mypy reports a
    # '"Sequence[int]" has no attribute "append" error', for example
    seq.append(5)

# This type checks, since lists satisfy the Sequence protocol
foo([1, 2, 3, 4])

# Same thing with tuples
foo((1, 2, 3, 4))

class CustomSequence(Sequence[int]):
    @overload
    def __getitem__(self, i: int) -> int: ...
    @overload
    def __getitem__(self, s: slice) -> Sequence[int]: ...
    def __getitem__(self, x: Union[int, slice]) -> Union[int, Sequence[int]]:
        if isinstance(x, int):
            return 1
        else:
            return [1, 2]

    def __len__(self) -> int:
        return 1

# Or any other kind of Sequence, actually.
foo(CustomSequence())

如果您想要一个通用的可变序列,请使用 MutableSequence。请注意,列表同时满足 Sequence 和 MutableSequence 协议。