Указывает, что параметр должен быть изменяемой ссылкой - PullRequest
5 голосов
/ 08 января 2020

С синтаксисом подсказки типа, заданным в 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]

или, если нет, как я могу определить такой тип, не заставляя инспекционные логи c думать, что это был специальный класс Mutable вместо List[int]? Очевидно, это будет использоваться как инструмент для разработчика, чтобы легче понять метод, вместо того, который будет использоваться для фундаментального изменения программы.

Для ясности, я знаю, что списки по определению являются изменяемыми , но мне интересно, есть ли способ определить , когда будет мутирован, например

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

Ответы [ 2 ]

3 голосов
/ 08 января 2020

Списки изменчивы в Python, поэтому явная ссылка на класс Mutable не требуется:

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]
1 голос
/ 08 января 2020

Списки по умолчанию считаются всегда изменяемыми. Поэтому, если вы хотите указать, что какой-либо список никогда не будет изменен, лучше указать это явно, используя вместо этого какой-либо интерфейс или протокол только для чтения, например typing.Sequence или typing.Collection.

Эти два типа означают иметь ту же семантику, что и соответствующие типы collection.ab c. Я полагаю, что вы можете думать о них примерно так же, как и о IReadOnlyCollection C#.

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...