17. any_and_object.py: note: In function "object_func":
any_and_object.py:8: error: Unsupported left operand type
for + ("object")
型ヒント :Any 型と object 型
from typing import Any
def any_func(x: Any, y: Any) -> Any:
return x + y
def object_func(x: object, y: object) -> object:
return x + y
mypy
object 型の操作は型チェカーでエラーとなる
理論的背景は「漸進的型付けとは何か」を参照
18. 型ヒント : 直和型 (Union Type)
●
直和型
– 関数型プログラミング言語でよく使われるデータ型
– 典型的にはツリーのデータ構造を簡潔に表現できる
●
単一の引数に対して少数の期待される型の集合
をとる
e = Union[Employee, Sequence[Employee]]
# OCaml バリアント型
type day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
# 第7回「代数データ型」でいろいろなデータを表してみる
23. 型ヒント :TypeVar の例
●
typing モジュールにいくつか定義されてる
# Some unconstrained type variables. These are used by the container types.
T = TypeVar('T') # Any type.
KT = TypeVar('KT') # Key type.
VT = TypeVar('VT') # Value type.
T_co = TypeVar('T_co', covariant=True) # Any type covariant containers.
V_co = TypeVar('V_co', covariant=True) # Any type covariant containers.
VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers.
T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
# A useful type variable with constraints. This represents string types.
# TODO: What about bytearray, memoryview?
AnyStr = TypeVar('AnyStr', bytes, str)
型の別名
24. 型ヒント : 型別名と直和型
●
型別名と直和型の違い
– 型パラメーターとなり得るか
from typing import Generic, TypeVar, Union
AnyStr = TypeVar('AnyStr', str, bytes)
class AnyStrNode(Generic[AnyStr]):
...
UnionStr = Union[str, bytes]
class UnionStrNode(Generic[UnionStr]):
...
mypy
error: Free type variable expected in Generic[...]
25. 型ヒント : ユーザー定義ジェネリック型
●
Generic という抽象基底クラスを継承する
from typing import Generic, TypeVar
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self) -> None:
self.items = [] # type: List[T]
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
s = Stack() # type: Stack[int]
s.push(3)
s.push(5)
s.pop()
s.push('x')
s = Stack[int]()
...
mypy
mypy
generics_stack.py:19: error:
Argument 1 to "push" of "Stack" has incompatible type "str";
expected "int"
error: Generic type not valid as an expression
any more (use '# type:' comment instead)
26. 型ヒント : 型消去
●
ユーザー定義のジェネリック型はインスタンス
化できる
from typing import TypeVar, Generic
T = TypeVar('T')
class Node(Generic[T]):
...
x = Node[T]() # The type inferred for x is Node[T].
print('x.__class__:', x.__class__)
y = Node[int]() # The type inferred for y is Node[int].
print('y.__class__:', y.__class__)
z = Node() # Inferred type is Node[Any].
print('z.__class__:', z.__class__)
実行時に型情報は
保持していない
$ python generics_type_erasure.py
x.__class__: __main__.Node[~T]
y.__class__: __main__.Node[~T]
z.__class__: __main__.Node[~T]
27. 型ヒント : 数値型階層 (numeric tower)
●
numbers モジュールに抽象基底クラスを定義
complex 型 int/float 型を許容する
def add_int(num: int) -> int:
return num + 1
print(add_int(1))
print(add_int(2.4))
print(add_int(complex('3+4J')))
# floatは割愛
def add_complex(num: complex) -> complex:
return num + complex('1+2J')
print(add_complex(7))
print(add_complex(8.14))
print(add_complex(complex('9+10J')))
mypy
error: Argument 1 to "add_int" has
incompatible type "float"; expected "int"
error: Argument 1 to "add_int" has
incompatible type "complex"; expected "int"