1. ホーム
  2. パイソン

[解決済み】*argsと**kwargsのタイプアノテーション

2022-03-27 06:45:42

質問

Pythonのタイプアノテーションを抽象的な基底クラスで試して、いくつかのインターフェースを書いているところです。の可能な型にアノテートする方法はありますか? *args**kwargs ?

例えば、ある関数の感覚的な引数が、(1) (2) (3) (4) (5)のいずれかであることをどのように表現するのでしょうか。 int または2つの int s? type(args) 与える Tuple というアノテーションが必要だと思いました。 Union[Tuple[int, int], Tuple[int]] しかし、これはうまくいきません。

from typing import Union, Tuple

def foo(*args: Union[Tuple[int, int], Tuple[int]]):
    try:
        i, j = args
        return i + j
    except ValueError:
        assert len(args) == 1
        i = args[0]
        return i

# ok
print(foo((1,)))
print(foo((1, 2)))
# mypy does not like this
print(foo(1))
print(foo(1, 2))

mypyのエラーメッセージです。

t.py: note: In function "foo":
t.py:6: error: Unsupported operand types for + ("tuple" and "Union[Tuple[int, int], Tuple[int]]")
t.py: note: At top level:
t.py:12: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:14: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 2 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"

mypyが関数呼び出しのためにこれを好まないのは理にかなっています。 tuple を呼び出しています。解凍後の追加も、よくわからないタイピングエラーが出ます。

のセンシブルな型はどのようにアノテートすればよいのでしょうか? *args**kwargs ?

解決方法は?

可変位置引数( *args ) と変数キーワード引数 ( **kw に対してのみ期待値を指定する必要があります。 1 このような引数は

より 任意の引数リストとデフォルトの引数値 セクション タイプヒント PEPです。

任意の引数リストにも型アノテーションをつけ、定義ができるようにします。

def foo(*args: str, **kwds: int): ...

は許容範囲であり、例えば以下のものはすべて有効な引数の型を持つ関数呼び出しであることを意味します。

foo('a', 'b', 'c')
foo(x=1, y=2)
foo('', z=0)

だから、こんな風にメソッドを指定したいんですね。

def foo(*args: int):

しかし、関数が1つか2つの整数値しか受けつけない場合は *args を使用し、1つの明示的な位置指定引数と2つ目のキーワード引数を使用します。

def foo(first: int, second: Optional[int] = None):

さて、この関数は実際には1つか2つの引数に制限されており、指定する場合は両方とも整数でなければなりません。 *args 常に は0以上を意味し、タイプヒントでより具体的な範囲に制限することはできない。