kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

PEP 483を読む(続き3)

型変数

X = TypeVar('X')で一意の型変数を宣言できます。名前は変数名と一致しなくてはなりません。デフォルトでは、型変数は可能なあらゆる型をとることができます。

uniqueを一意と訳したけれども何がuniqueなんだろう
同じ名前で2回は宣言できない、くらいの話かな

$ cat practice.py
from typing import TypeVar

T = TypeVar('T')
T = TypeVar('T')
$ mypy practice.py
practice.py:4: error: Invalid assignment target
practice.py:4: error: Cannot redefine 'T' as a type variable
practice.py:4: error: "object" not callable

怒られた

逆に、宣言した変数をあっちこっちで使い回すことはできるのかな
できると思うけど

$ cat practice.py
from typing import TypeVar

T = TypeVar('T')

def first(a: T, b: T) -> T:
    return a

def second(a: T, b: T) -> T:
    return b

print(first(1, 2))
print(first("a", "b"))

print(second(1, 2))
print(second("a", "b"))
$ mypy practice.py
$

できた
firstのTとsecondのTはなんの関係もないよね?

Y = TypeVar('Y', t1, t2, ...)はt1等の型に制限され、Union[t1, t2, ...]と似たふるまいをします。制限された型変数はt1等の型*しか*とりません。サブクラスはt1等の最も派生した基底クラス(most-derived base class)に置き換えられます。

ちょっと何を言ってるのかわからない>最後の文

制限付き型変数のついた関数のアノテーション

S = TypeVar('S', str, bytes)

def longest(first: S, second: S) -> S:
    return first if len(first) >= len(second) else second

result = longest('a', 'abc') # resultの推論された型はstr

result = longest('a', b'abc') # 静的型チェックで失敗

bytesってstrの部分型じゃないってことだっけ?

>>> isinstance('aaaaa', str)
True
>>> isinstance(b'aaaaa', str)
False
>>> isinstance('aaaaa', bytes)
False
>>> isinstance(b'aaaaa', bytes)
True

そういうわけではなさそう
似てるけど縁もゆかりもない型ってことでいいのかな
ということは上の例は型チェックで失敗して当然ってこと?

この例では、longestの引数が両方とも同じ型を持っている必要があります。もし引数が共通なstrのサブクラスのインスタンスであっても返り値の型はそのサブクラスではなく、strとなります。

これが「サブクラスはt1等の最も派生した基底クラスに置き換えられます」の説明だと思うんだけど
やっぱりよく意味がわからない

こういうのがどういうとき便利なのかもちょっとイメージできてない

もし型変数が制限されていなければ、返り値の型は共通のサブクラスになります。

これはわかる

Unionの場合は、返り値の型もUnionになります。

これもわかる