SlideShare a Scribd company logo
1 of 72
Download to read offline
Python と
型チェッカー
2018-05-19 Tetsuya Morimoto
自己紹介
●
森本 哲也
– twitter: @t2y
●
ポータルサイトの会社
– オブジェクトストレージの開発・運用
●
業務では Go 言語で開発
– 普段使いのツールやプロトタイピングに Python
●
エキスパート Python プログラミング改訂2版
– Python 3.5 ( 翻訳は 3.6) を対象
最近のニュース
●
Pyre: Fast Type Checking for Python
– 概要から引用
Facebook 社も Instagram 社も大規模に Python を使っています。私たちは Python の表現力、
柔軟性、開発における生産性をとても好んでいます。しかし、数百万行といった大規模コード
ベースの保守を考えると、そういった良いところにも陰りがみえてきます。
●
静的な保証がないと、既存のコードベースを安全に変更することが難しくなり、コードのエラーが発生しや
すくなって静的型付けされたコードと比べて開発が遅くなる
●
コード検索、コード補完、ナビゲーション、リファクタリングサポートなどの高品質なツールを構築するこ
とが難しい。こういったツールがないと、大規模コードベースで作業するときに特に弊害となる
これらの問題に対処するために、私たちは高速な PEP 484 互換の型チェッカーと深い静的解析
ツールを構築するための優れたプラットフォームの双方を兼ね備えた Pyre を構築しました。
型ヒント付きコードのサンプル
import json
import sys
from pprint import pformat
from typing import Any, Dict
def pretty_format(data: Dict[str, Any]) -> str:
return pformat(data, width=1)
def main(raw_data: str) -> None:
data = pretty_format(json.loads(raw_data))
data.append('mypy') # error: "str" has no attribute "append"
if __name__ == '__main__':
raw_data: str = sys.argv[1]
main(raw_data)
背景
5
これまでの経緯
●
Python 3.5 リリース
– PEP 484 型ヒント→ typing モジュールを提供
– mypy-lang 0.2.0 (2015-04-06)
●
Python 3.6 リリース
– PEP 526 変数アノテーション
– mypy 0.470 (2017-01-13)
●
いま
– mypy 0.600 (2018-05-02)
●
Python 3.7 予定
2015-09-13
2016-12-23
2018-06-15
この資料で
扱う範囲
最近の mypy のリリース履歴
●
0.600: mypy daemon
●
0.590: 型情報のパッケージングを試験導入 (PEP561)
●
...
●
0.530: structural subtyping を試験導入 (PEP544)
●
0.510: ClassVar サポート
●
...
●
0.470: pypi のパッケージ名を mypy-lang から mypy へ移行
●
(mypy-lang) 0.4 2017-01-13
2018-05-02
2017-10-06
2018-04-13
Python の開発スケジュールと並行して mypy に機能を試験導入している
Python への機能追加の流れ
1. サードパーティでやってみよ
mypy の開発は 2012 年開始 (Python3.2/3.3)
2. 標準ライブラリに入れましょう
型ヒントは typing モジュールとして提供 (Python3.5)
3. C 言語拡張でなんとかしましょう
typed_ast: 型コメントを扱える / 高速 ast ライブラリ
4. 言語に変更を加えましょう (Python3.6/3.7 PEP 526/560)
Python のコア機能の拡張は保守的に進められる
新規の機能がいきなり言語のコアに入ることは基本的にない
イマココ!
typing/mypy
最近の機能
9
mypy daemon
●
mypy 0.600 でサポート
– まだ beta レベル
●
数ファイル変更したときに毎回 mypy を実行す
るのはパフォーマンスがよくない
●
dmypy を使うと大規模なコードベースでは
mypy コマンドと比べて数十倍速いらしい
mypy command
$ time mypy --no-incremental sphinx
real 0m21.968s
user 0m20.986s
sys 0m0.769s
$ time mypy --follow-imports=error sphinx
sphinx/events.py: note: In member "disconnect" of class "EventManager":
sphinx/events.py:71:5: error: Missing return statement
real 0m16.784s
user 0m16.366s
sys 0m0.361s
mypy daemon
$ dmypy start -- --follow-imports=error
Daemon started
$ ps ax|grep dmypy
59452 ?? S 0:00.00 path/to/dmypy start -- --follow-imports=error
$ time dmypy check sphinx
real 0m20.714s
user 0m0.116s
sys 0m0.035s
$ time dmypy check sphinx
Daemon crashed!
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'type_vars'
エラーになって計測できなかった。。。
TypedDict(1)
●
mypy_extensions の拡張機能
– 試験的機能だが、 mypy 0.530 から公式サポート
●
厳密なディクショナリの型定義
– 特定の key のみに限定したいとき
– value の型が複数あるようなとき
– すべての要素を指定させたいとき
TypedDict(2)
from typing import Dict, Any, Union
blade_runner: Dict[str, Any] = {'name': 'Blade Runner', 'year': 1982}
toy_story: Dict[str, Union[str, int]] = {'name': 'Toy Story', 'year': 1995}
from mypy_extensions import TypedDict
Movie = TypedDict('Movie', {'name': str, 'year': int})
blade_runner: Movie = {'name': 'Blade Runner', 'year': 1982}
toy_story = Movie(name='Toy Story', year=1995)
Movie はコンストラクタとしても使える
TypedDict を関数の引数に渡したときは型アノテーションはか
書かなくても mypy が型推論する
TypedDict(3)
name, year が定義されていないと型チェックでエラーになる
total=False を渡すとエラーにならない
the_rock = Movie(name='The Rock')
# error: Key 'year' missing for TypedDict "Movie"
Movie = TypedDict('Movie', {'name': str, 'year': int}, total=False)
the_rock = Movie(name='The Rock')
TypedDict(4)
3.6 からクラス構文でも定義できる
クラスだと型定義を継承することもできる
from mypy_extensions import TypedDict
class Movie(TypedDict):
name: str
year: int
blade_runner: Movie = {'name': 'Blade Runner', 'year': 1982}
class ExtraMovie(Movie):
director: str
the_rock = ExtraMovie(name='The Rock', year=1996, director='Michael Bay')
NamedTuple(1)
●
TypedDict 同様に 3.6 からクラス構文をつかっ
た NamedTuple の定義ができる
NamedTuple(2)
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(x=1, y=2)
print(p.z) # Error: Point has no attribute 'z'
from typing import NamedTuple
Point = NamedTuple('Point', [('x', int), ('y', int)])
p = Point(x=1, y='x')
# Error: Argument has incompatible type "str"; expected "int"
NamedTuple(3)
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
p = Point(x=1, y='x')
# Error: Argument has incompatible type "str"; expected "int"
3.6 からクラス構文でも定義できる
NamedTuple の型定義は継承できない
NewType(1)
●
typing に 3.5.2 で追加
●
論理的なエラーチェックのためにクラスを生成
すると実行時オーバーヘッドになる
●
クラスを生成せずに型チェックできるヘルパー
関数を提供
NewType(2)
class UserId(int):
pass
def name_by_id(user_id: UserId) -> str:
...
from typing import NewType
UserId = NewType('UserId', int)
UserId('user')
# error: Argument 1 to "UserId" has incompatible type "str"; expected "int"
name_by_id(42)
# error: Argument 1 to "name_by_id" has incompatible type "int"; expected "UserId"
name_by_id(UserId(42)) # OK
num = UserId(5) + 1 # type: int
NewType の実装
def NewType(name, tp):
"""NewType creates simple unique types with almost zero
runtime overhead. NewType(name, tp) is considered a subtype of tp
by static type checkers. At runtime, NewType(name, tp) returns
a dummy function that simply returns its argument. Usage::
"""
def new_type(x):
return x
new_type.__name__ = name
new_type.__supertype__ = tp
return new_type
ソースファイルのオーバーロード
●
当初 PEP 484 では @overload デコレーターは
スタブファイルのみでのサポートと記述されて
いたが、その制約は見直された
– Relax constraints on @overload. It may occur in
modules if followed by a non-@overload version.
●
ソースコードにも記述して mypy で型チェック
できるようになった
●
Union 型では厳密に定義できないときがある
●
mypy 0.510 でサポート
リストの添字アクセス (Union)
from typing import Sequence, TypeVar, Union
T = TypeVar('T')
class MyList(Sequence[T]):
def __getitem__(self, index: Union[int, slice]) -> Union[T, Sequence[T]]:
if isinstance(index, int):
... # Return a T here
elif isinstance(index, slice):
... # Return a sequence of Ts here
else:
raise TypeError(...)
リストの添字アクセス
- インデックス値かスライスを指定したら T か Sequence[T] を返す
リストの添字アクセス (overload)
リストの添字アクセス
- インデックス値を指定したら T を返す
- スライスを指定したら Sequence[T] を返す
from typing import overload, Sequence, TypeVar, Union
T = TypeVar('T')
class MyList(Sequence[T]):
@overload
def __getitem__(self, index: int) -> T:
pass # Don't put code here
@overload
def __getitem__(self, index: slice) -> Sequence[T]:
pass # Don't put code here
ジェネリック関数を返す関数
●
典型的な用途としてはデコレーター関数
●
mypy 0.510 でサポート
デコレート関数の型チェック
from typing import TypeVar, Callable, Any, cast
T = TypeVar('T', bound=Callable[..., Any])
def logged(description: str) -> Callable[[T], T]:
def decorator(f: T) -> T:
def wrapper(*args, **kwargs):
print('entering:', description)
value = f(*args, **kwargs)
print('leaving:', description)
return cast(T, wrapper)
return decorator
@logged('system initialization')
def init() -> None:
print('do something')
init(1) # error: Too many arguments (signature is correctly preserved)
Metaclass
●
シンプルな metaclass の型チェク
●
mypy0.501 でサポート
class Meta(type):
def __add__(self, x: str) -> str:
return 'a' + x
class C(metaclass=Meta):
...
print(C + 'x') # Okay
print(C + 1) # error: Unsupported operand types for + ("Type[C]" and "int")
循環インポート対策
●
型アノテーションを書くためにユーザー定義型
をインポートしていくうちに循環インポートが
発生しやすい
– mypy も循環インポートをうまく扱えなかった
●
mypy0.501 で対応
– 実行時にも影響を与えないやりかた
from typing import List, TYPE_CHECKING
if TYPE_CHECKING:
import bar
型ヒントと
関連 PEP
30
型ヒント関連の PEP の履歴
●
PEP 484 型ヒント
– Nominal Subtyping の型チェックのみ
●
PEP 526 変数アノテーションの構文
– Structural Subtyping に必要
●
Python 3.7
– PEP 560 typing モジュールとジェネリック型のコアサポート
– PEP 563 アノテーションの評価の延期
– PEP 544 プロトコル : Structural Subtyping
– PEP 561 型情報のパッケージング
Python 3.5
Python 3.6
( 承認 )
( 承認 )
延期
延期
mypy
support
PEP 560 typing モジュールと
ジェネリック型のコアサポート
●
typing モジュールのジェネリック型の様々な問題
– 実行時オーバーヘッド
– メタクラスの競合
– メタクラスハックによるバグの温床
●
2 つの特殊メソッドを追加
– __class_getitem__: クラスの添字のときに呼ばれる
– __mro_entries__: クラス定義の親リストにクラスオブ
ジェクトではないものが指定されたときに呼ばれる
クラスの添字を扱うメタクラス
class MetaSubscript(type):
def __new__(cls, name, bases, namespace, **kwds):
return super().__new__(cls, name, bases, dict(namespace))
def __getitem__(cls, params):
cls.params = params
return cls.__class__(cls.__name__, cls.__bases__, cls.__dict__)
class MyGeneric(metaclass=MetaSubscript):
pass
g = MyGeneric[str]()
print(MyGeneric.params) # <class 'str'>
クラスの作成時に metaclass.__new__ が呼ばれる
例えば、型アノテーションのためにクラスを
インポートしたときにオーバーヘッドになってしまう
PEP 563 アノテーションの評価の先送り
●
関数定義時点でアノテーションが評価されること
による問題
– 前方参照ができない
– インポート時に型ヒントが実行される
●
アノテーションを評価しないオプション
– Python 4.0 からデフォルトになる
from __future__ import annotations
前方参照のコード例
class A:
def f(self):
return B()
b = B() # NameError: name 'B' is not defined
def f():
b = B()
f() # NameError: name 'B' is not defined
a = A()
a.f() # NameError: name 'B' is not defined
class B:
pass
前方参照の型アノテーション
( 型アノテーションのみサポート )
from __future__ import annotations
class C:
field = 'c_field'
def method(self) -> C.field:... # this is OK
def method(self) -> field:... # this is OK
def method(self) -> C.D:... # this is OK
def method(self) -> D:... # this is OK
class D:
field2 = 'd_field'
def method(self) -> C.D.field2:... # this is OK
def method(self) -> D.field2:... # this is OK
def method(self) -> field2:... # this is OK
def method(self) -> field:... # this FAILS, class D doesn't
# see C's attributes, This was
# already true before this PEP.
PEP 544 プロトコル :
Structural Subtyping
●
別名 : 静的なダックタイピング
●
型ヒントの大きなマイルストーン?
●
https://github.com/python/typing/issues/11
– 作成日 :2014-10-16 (3.5 のリリース前 )
– 型ヒントが導入される以前から議論されていた
– 3.7 で提案されたが、残念ながら延期された
●
Python プログラマーにとって、より自然なセマ
ンティクスで型アノテーションを書ける
37
ダックタイピング
●
型の安全性における duck test を満たすアプリ
ケーションをダックタイピングと呼ぶ
– duck test とは、論理的推論方法 ( 帰納法 ) の一種
– " もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである "
●
型チェックを実行時に遅延させる
– 動的型付けやリフレクションを用いて実装される
●
ダックタイピングは
オブジェクトのメソッドや
プロパティの有無で決定される
def talk(x, y):
x.greet(y.name)
2 つのクラスが型として互換か
●
Nominal Subtyping ( 名前的部分型 )
– クラスを定義してクラス階層で部分型が成立する
– 継承によって実現する
●
Structural Subtyping ( 構造的部分型 )
– すべての属性 ( プロパティ ) とメソッドをもっている
なら部分型が成立する
– mypy は Protocol クラスを介してサポートする
from typing_extensions import Protocol
ダックタイピングと似ている!
Nominal Subtyping ( 名前的部分型 )
from typing import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int:
len(items)
result: int = collect(Bucket()) # Passes type check
Structural Subtyping ( 構造的部分型 )
from typing import Iterator, Iterable
class Bucket:
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int:
len(items)
result: int = collect(Bucket()) # Passes type check
抽象基底クラス (ABC)
from abc import ABCMeta, abstractmethod
class InterfaceGreet(metaclass=ABCMeta):
@property
@abstractmethod
def name(self): ...
@abstractmethod
def greet(self, other): ...
class Person(InterfaceGreet):
name = ''
p = Person() # error: Cannot instantiate abstract class
# 'Person' with abstract attribute 'greet'
これまでのやり方
Python でインターフェースっぽいもの
ユーザー定義プロトコル (1)
from typing_extensions import Protocol
class Greetable(Protocol):
name: str
def greet(self, other: str) -> None: ...
class Person:
def __init__(self, name: str) -> None:
self.name = name
p: Greetable = Person(' もりもと ')
# error: Incompatible types in assignment
# (expression has type "Person", variable has type "Greetable")
# note: 'Person' is missing following 'Greetable' protocol member:
# note: greet
Greetable を継承しなくて良い!
ユーザー定義プロトコル (1)
from typing_extensions import Protocol
class Greetable(Protocol):
name: str
def greet(self, other: str) -> None: ...
class Person:
def __init__(self, name: str) -> None:
self.name = name
def greet(self, other: str) -> None:
print(' こんにちはー {}'.format(other))
class Cat:
def __init__(self, name: str) -> None:
self.name = name
def greet(self, other: str) -> None:
print(' にゃあー {}'.format(other))
def greet_each_other(x: Greetable, y: Greetable) -> None:
x.greet(y.name)
y.greet(x.name)
def main() -> None:
morimoto = Person(' もりもと ')
tama = Cat(' たま ')
greet_each_other(morimoto, tama)
ユーザー定義プロトコル (2)
class Anonymous:
def greet(self, other: str) -> None:
print(' やあ {}'.format(other))
def greet_each_other(x: Greetable, y: Greetable) -> None:
x.greet(y.name)
y.greet(x.name)
def main() -> None:
morimoto = Person(' もりもと ')
anonymous = Anonymous()
greet_each_other(morimoto, anonymous)
# error: Argument 2 to "greet_each_other" has incompatible type "Anonymous"; expected "Greetable"
# note: 'Anonymous' is missing following 'Greetable' protocol member:
# note: name
エラーメッセージもわかりやすい
PEP 561 型情報のパッケージング
●
mypy は mypy を実行する python インタープリ
ター向けにインストールされたパッケージディレ
クトリから型情報を含むパッケージを探索する
– 複数の仮想環境を扱うときなどうまくいかない
●
型情報を配布するパッケージングの仕組み
1.コード内に型アノテーションを記述している
2.実行コードと一緒に型情報の stub を提供する
3.型情報の stub を独立したパッケージで提供する
コード内に型アノテーションを記述
setup.py
package_a/
__init__.py
lib.py
py.typed
from distutils.core import setup
setup(
name="SuperPackageA",
author="Me",
version="0.1",
package_data={"package_a": ["py.typed"]},
packages=["package_a"]
)
py.typed を作る
実行コードと一緒に
型情報の stub を提供する
setup.py
package_b/
__init__.py
lib.py
lib.pyi
py.typed
from distutils.core import setup
setup(
name="SuperPackageB",
author="Me",
version="0.1",
package_data={"package_b": ["py.typed", "lib.pyi"]},
packages=["package_b"]
)
py.typed と lib.pyi を作る
型情報の stub を独立した
パッケージで提供する
setup.py
package_c-stubs/
__init__.pyi
lib.pyi
from distutils.core import setup
setup(
name="SuperPackageC",
author="Me",
version="0.1",
package_data={
"package_c-stubs": ["__init__.pyi", "lib.pyi"]
},
packages=["package_c-stubs"]
)
__init__.pyi と lib.pyi を作る
業務で型チェックを試している知人から
●
いま型アノテーションをつけようとしたときに
遭遇する課題
– サードパーティで型アノテーションがついていな
い、もしくはスタブが提供されていない
– 社内リポジトリにスタブファイルを作ったりしている
●
ローカルで CI 用途に使うとしても型情報のパッ
ケージングすごく大事
mypy と
関連プロジェクト
51
mypy プロジェクト (1)
●
http://mypy-lang.org/
●
Python 本体は型ヒントの構文のみを標準化
– 標準ライブラリとして typing モジュールを提供
●
型チェッカーはサードパーティ
– mypy は型チェッカーの参照実装のようなもの
– https://github.com/python/mypy
●
リポジトリは python organization 配下にある
●
コミュニケーション (ML ではなく Gitter)
– https://gitter.im/python/typing
mypy プロジェクト (2)
●
コア開発者
– Jukka Lehtosalo: mypy 作者 (@Dropbox)
– Guido van Rossum: python 作者 (@Dropbox)
– David Fisher: (@Dropbox)
– Ivan Levkivskyi: 理論物理学 (@University of Bern)
– Elazar Gershuni: (@Technion)
– Michael J. Sullivan: (@Dropbox)
●
直近でコントリビュートしている上位開発者
Dropbox 社が強い関心をもっているのがわかる
mypy プロジェクト (3)
●
mypy_extensions
– https://pypi.org/project/mypy_extensions/
●
コードは mypy リポジトリの内部にある
– https://github.com/python/mypy/tree/master/exte
nsions
●
mypy の試験的な機能や拡張を提供
– TypedDict( 後述 ) を使うときに必要
●
Mypy 0.530 Released
typing プロジェクト (1)
●
https://github.com/python/typing
– typing モジュールの開発や議論
– 当初の予定では 3.5.0 から 3.7.0 までだった?
●
3.7.0 で typing モジュールの“ provisional" を外す予定
– https://github.com/python/typing/issues/495#i
ssuecomment-342644111
●
typing を標準ライブラリから外すかどうかの議論
●
少なくとも 3.7.0 では“ provisional" にしよう
typing プロジェクト (2)
●
コア開発者
– Guido van Rossum: python 作者 (@Dropbox)
– Ivan Levkivskyi: 理論物理学 (@University of Bern)
– Łukasz Langa: (@Facebook)
– Andrey Vlasovskikh: (@JetBrains)
– Jukka Lehtosalo: mypy 作者 (@Dropbox)
●
コントリビュートの上位 5 人
mypy/typing ともに Guido 氏がイニシアティブをもって取り組んでいる
typing プロジェクト (3)
●
typing_extensions
– https://pypi.org/project/typing-extensions/
●
コードは typing リポジトリの内部にある
– https://github.com/python/typing/tree/master/ty
ping_extensions
●
typing の試験的な機能や型を提供
●
旧バージョン (3.5/3.6) のバックポートとしても
使える
Protocol は typing_extensions からインポートできる
typeshed リポジトリ
●
https://github.com/python/typeshed
– 型チェックのための stub 共有リポジトリ
– TypeScript でいうところの DefinitelyTyped
●
標準ライブラリの stub を提供
●
サードパーティはまだ少し
– 追加するには対象ライブラリのメンテナーに連絡し
て許可を得る
typed_ast プロジェクト
●
https://github.com/python/typed_ast
– mypy の依存パッケージとしてインストールされる
– Python2.7/3 向けのパーサーを提供する
– 標準 ast ライブラリと完全互換
●
型コメントを扱える
●
標準 ast のバグは直さない (upstream で修正しない限り )
– 標準 ast よりも高速らしい
その他の
ツール
60
Cython と型アノテーション
●
Pure Python Mode
– Python 文法の範囲内でコードを記述
– 最適化したいところだけでコレータを付与
– 型ヒントの構文で Cython の型情報を記述
from ctypes import c_char, POINTER
# Before
def feeder(c_string):
cdef char* c_string = NULL
# After
def feeder(c_string: POINTER(c_char)) -> None:
pass
型アノテーションの自動生成
●
PyAnnotate (@Dropbox)
– https://github.com/dropbox/pyannotate
– Python2/3 向け、型コメントを生成
●
MonkeyType (@Instagram)
– https://github.com/Instagram/MonkeyType
– Python3 向け、 stub/ 型アノテーションを生成
●
リファレンス
– Python の型アノテーションを自動生成する
●
PyAnnnotate と MonkeyType の調べてみた
その他の型チェッカー
●
PyCharm: Type Hinting in PyCharm
– PEP 563 アノテーションの評価の延期
– 型ヒントや変数アノテーションのサポート
– Typeshed との連携
●
Pyre: https://pyre-check.org/
– 高速でスケーラブルな型チェッカー
まとめ
64
型ヒントの成功の兆し?
●
typing/mypy の開発は十分に活発にみえる
– パフォーマンスについて懸念されるようになった
– 型ヒント関連の PEP も継続的に提案されている
●
大規模なコードベースをもつ企業での運用
– Dropbox/Zulip
●
ノウハウやツールを公開
●
Guido, Jukka 氏も活発に開発
– Facebook/Instagram
●
エディタや CI 連携を考慮した
実務的な型チェッカーやライブラリを公開
今後の実運用からの
フィードバックも
期待される
typing は 3.8 で stable ?
●
3.5 で型ヒントを導入したとき
– 賛否両論で議論が盛り上がった
– 3.7 で provisional→stable の予定だったが延期
– それでも開発は活発にみえる
●
3.8 の期待
– Structural Subtyping がサポートされるはず
– mypy は先行サポートしているので待つ必要はない
今後のサードパーティの対応?
●
typeshed にはまだまだ少ない
– スタブのメンテはしんどいよね
●
よく使われているサードパーティがどのぐらい
対応していくか
– 2020 年の Python2 のサポート終了
– 2/3 対応から 3 のコードベースへ移行?
●
型アノテーションの自動生成の未来
– いまツールが公開されたところ
リファレンス
68
Python 開発
●
Python ドキュメント
– What’s New In Python 3.7
– typing — 型ヒントのサポート
●
DSAS 開発者の部屋
– 最近のPython-dev(2017-12)
– 最近のPython-dev(2017-06)
– 最近のPython-dev (2017-05)
●
言語設計者たちが考えること O'Reilly Japan, Inc.
型ヒント
●
What is Gradual Typing: 漸進的型付けとは何か
●
PEP
– [翻訳] PEP 0484 -- 型ヒント (Type Hints)
●
Python と型ヒント (Type Hints) と #pyconjp
– PEP 526 -- Syntax for Variable Annotations
– PEP 544 -- Protocols: Structural subtyping (static duck typing)
– PEP 560 -- Core support for typing module and generic types
– PEP 561 -- Distributing and Packaging Type Information
– PEP 563 -- Postponed Evaluation of Annotations
●
[翻訳] Python の静的型、すごい mypy!
型システム
●
https://en.wikipedia.org/wiki/Duck_typing
●
https://en.wikipedia.org/wiki/Structural_ty
pe_system
●
https://en.wikipedia.org/wiki/Subtyping
●
第4回 関数型言語とオブジェクト指向,およびOC
amlの"O"について
その他のツール
●
Cython: Python Typing Proposal
●
Dropbox releases PyAnnotate -- auto-genera
te type annotations for mypy
●
Dropbox releases mypy-protobuf
●
Let your code type-hint itself: introducing
open source MonkeyType
●
Pycon2017 instagram keynote
●
スライド内のサンプルコード
– https://github.com/t2y/python-study/tree/mas
ter/MiniOsaka

More Related Content

What's hot

ChatGPT 人間のフィードバックから強化学習した対話AI
ChatGPT 人間のフィードバックから強化学習した対話AIChatGPT 人間のフィードバックから強化学習した対話AI
ChatGPT 人間のフィードバックから強化学習した対話AIShota Imai
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.kiki utagawa
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときShintarou Okada
 
Python と型アノテーション
Python と型アノテーションPython と型アノテーション
Python と型アノテーションK Yamaguchi
 
Prophet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールProphet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールhoxo_m
 
FastAPIを使って 機械学習モデルをapi化してみた
FastAPIを使って 機械学習モデルをapi化してみたFastAPIを使って 機械学習モデルをapi化してみた
FastAPIを使って 機械学習モデルをapi化してみたSho Tanaka
 
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3Preferred Networks
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みMasahiro Sakai
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかShunsukeNakamura17
 
MLflowによる機械学習モデルのライフサイクルの管理
MLflowによる機械学習モデルのライフサイクルの管理MLflowによる機械学習モデルのライフサイクルの管理
MLflowによる機械学習モデルのライフサイクルの管理Takeshi Yamamuro
 
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習Hori Tasuku
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpsonickun
 
ブラックボックス最適化とその応用
ブラックボックス最適化とその応用ブラックボックス最適化とその応用
ブラックボックス最適化とその応用gree_tech
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろうKota Mizushima
 
論理回路シミュレータ Logisim の使い方
論理回路シミュレータ Logisim の使い方論理回路シミュレータ Logisim の使い方
論理回路シミュレータ Logisim の使い方Takashi Kawanami
 
モデル高速化百選
モデル高速化百選モデル高速化百選
モデル高速化百選Yusuke Uchida
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021Hiroshi Tokumaru
 

What's hot (20)

NumPy闇入門
NumPy闇入門NumPy闇入門
NumPy闇入門
 
ChatGPT 人間のフィードバックから強化学習した対話AI
ChatGPT 人間のフィードバックから強化学習した対話AIChatGPT 人間のフィードバックから強化学習した対話AI
ChatGPT 人間のフィードバックから強化学習した対話AI
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるとき
 
Python と型アノテーション
Python と型アノテーションPython と型アノテーション
Python と型アノテーション
 
Prophet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールProphet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツール
 
FastAPIを使って 機械学習モデルをapi化してみた
FastAPIを使って 機械学習モデルをapi化してみたFastAPIを使って 機械学習モデルをapi化してみた
FastAPIを使って 機械学習モデルをapi化してみた
 
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3
Optunaを使ったHuman-in-the-loop最適化の紹介 - 2023/04/27 W&B 東京ミートアップ #3
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
 
MLflowによる機械学習モデルのライフサイクルの管理
MLflowによる機械学習モデルのライフサイクルの管理MLflowによる機械学習モデルのライフサイクルの管理
MLflowによる機械学習モデルのライフサイクルの管理
 
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
 
ブラックボックス最適化とその応用
ブラックボックス最適化とその応用ブラックボックス最適化とその応用
ブラックボックス最適化とその応用
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろう
 
論理回路シミュレータ Logisim の使い方
論理回路シミュレータ Logisim の使い方論理回路シミュレータ Logisim の使い方
論理回路シミュレータ Logisim の使い方
 
Docker Tokyo
Docker TokyoDocker Tokyo
Docker Tokyo
 
モデル高速化百選
モデル高速化百選モデル高速化百選
モデル高速化百選
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 

Similar to Pythonと型チェッカー

20170131 python3 6 PEP526
20170131 python3 6 PEP526 20170131 python3 6 PEP526
20170131 python3 6 PEP526 masahitojp
 
はじめてのPython
はじめてのPythonはじめてのPython
はじめてのPythonKatsumi Honda
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Springanyakichi
 
TensorFlowをもう少し詳しく入門
TensorFlowをもう少し詳しく入門TensorFlowをもう少し詳しく入門
TensorFlowをもう少し詳しく入門tak9029
 
ひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すAromaBlack
 
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)Hiro H.
 
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用de:code 2017
 
Learning Template Library Design using Boost.Geomtry
Learning Template Library Design using Boost.GeomtryLearning Template Library Design using Boost.Geomtry
Learning Template Library Design using Boost.GeomtryAkira Takahashi
 
dataclassとtypehintを使ってますか?
dataclassとtypehintを使ってますか?dataclassとtypehintを使ってますか?
dataclassとtypehintを使ってますか?Atsushi Hayakawa
 
Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Yasutomo Kawanishi
 
Introduction to Numpy (and Python) [JPN]
Introduction to Numpy (and Python) [JPN]Introduction to Numpy (and Python) [JPN]
Introduction to Numpy (and Python) [JPN]MasaruOinaga
 
「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"Ken'ichi Matsui
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Seiya Tokui
 
魂のコーディング
魂のコーディング魂のコーディング
魂のコーディングDaisuke Tasaki
 
Twitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hackTwitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hackkimukou_26 Kimukou
 
Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Jun MITANI
 

Similar to Pythonと型チェッカー (20)

20170131 python3 6 PEP526
20170131 python3 6 PEP526 20170131 python3 6 PEP526
20170131 python3 6 PEP526
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
はじめてのPython
はじめてのPythonはじめてのPython
はじめてのPython
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Spring
 
TensorFlowをもう少し詳しく入門
TensorFlowをもう少し詳しく入門TensorFlowをもう少し詳しく入門
TensorFlowをもう少し詳しく入門
 
ひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指すひのきのぼうだけで全クリ目指す
ひのきのぼうだけで全クリ目指す
 
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
 
Boost Fusion Library
Boost Fusion LibraryBoost Fusion Library
Boost Fusion Library
 
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
 
Learning Template Library Design using Boost.Geomtry
Learning Template Library Design using Boost.GeomtryLearning Template Library Design using Boost.Geomtry
Learning Template Library Design using Boost.Geomtry
 
What is template
What is templateWhat is template
What is template
 
dataclassとtypehintを使ってますか?
dataclassとtypehintを使ってますか?dataclassとtypehintを使ってますか?
dataclassとtypehintを使ってますか?
 
Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~
 
Introduction to Numpy (and Python) [JPN]
Introduction to Numpy (and Python) [JPN]Introduction to Numpy (and Python) [JPN]
Introduction to Numpy (and Python) [JPN]
 
「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用
 
魂のコーディング
魂のコーディング魂のコーディング
魂のコーディング
 
Teclab3
Teclab3Teclab3
Teclab3
 
Twitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hackTwitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hack
 
Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)
 

More from Tetsuya Morimoto

ビジネスパーソン x プログラミング
ビジネスパーソン x プログラミングビジネスパーソン x プログラミング
ビジネスパーソン x プログラミングTetsuya Morimoto
 
チケット駆動開発のススメ
チケット駆動開発のススメチケット駆動開発のススメ
チケット駆動開発のススメTetsuya Morimoto
 
PyLadies Tokyo 二周年記念パーティ LT
PyLadies Tokyo 二周年記念パーティ LTPyLadies Tokyo 二周年記念パーティ LT
PyLadies Tokyo 二周年記念パーティ LTTetsuya Morimoto
 
PyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッションPyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッションTetsuya Morimoto
 
ストリーミングのげんざい
ストリーミングのげんざいストリーミングのげんざい
ストリーミングのげんざいTetsuya Morimoto
 
Python3 プログラミング勉強会
Python3 プログラミング勉強会Python3 プログラミング勉強会
Python3 プログラミング勉強会Tetsuya Morimoto
 
Ikazuchi introduction for Europython 2011 LT
Ikazuchi introduction for Europython 2011 LTIkazuchi introduction for Europython 2011 LT
Ikazuchi introduction for Europython 2011 LTTetsuya Morimoto
 
Python界隈の翻訳プロジェクト
Python界隈の翻訳プロジェクトPython界隈の翻訳プロジェクト
Python界隈の翻訳プロジェクトTetsuya Morimoto
 
エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半Tetsuya Morimoto
 
エキ Py 読書会02 2章前半
エキ Py 読書会02 2章前半エキ Py 読書会02 2章前半
エキ Py 読書会02 2章前半Tetsuya Morimoto
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7Tetsuya Morimoto
 

More from Tetsuya Morimoto (16)

ビジネスパーソン x プログラミング
ビジネスパーソン x プログラミングビジネスパーソン x プログラミング
ビジネスパーソン x プログラミング
 
チケット駆動開発のススメ
チケット駆動開発のススメチケット駆動開発のススメ
チケット駆動開発のススメ
 
PyLadies Tokyo 二周年記念パーティ LT
PyLadies Tokyo 二周年記念パーティ LTPyLadies Tokyo 二周年記念パーティ LT
PyLadies Tokyo 二周年記念パーティ LT
 
PyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッションPyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッション
 
Hyper Introduction
Hyper IntroductionHyper Introduction
Hyper Introduction
 
ストリーミングのげんざい
ストリーミングのげんざいストリーミングのげんざい
ストリーミングのげんざい
 
Python3 プログラミング勉強会
Python3 プログラミング勉強会Python3 プログラミング勉強会
Python3 プログラミング勉強会
 
PyCon 2012 紀行
PyCon 2012 紀行PyCon 2012 紀行
PyCon 2012 紀行
 
Sphinx 社内勉強会
Sphinx 社内勉強会Sphinx 社内勉強会
Sphinx 社内勉強会
 
Ikazuchi introduction for Europython 2011 LT
Ikazuchi introduction for Europython 2011 LTIkazuchi introduction for Europython 2011 LT
Ikazuchi introduction for Europython 2011 LT
 
Python界隈の翻訳プロジェクト
Python界隈の翻訳プロジェクトPython界隈の翻訳プロジェクト
Python界隈の翻訳プロジェクト
 
エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半
 
エキ Py 読書会02 2章前半
エキ Py 読書会02 2章前半エキ Py 読書会02 2章前半
エキ Py 読書会02 2章前半
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7
 
Ex py intro-20100630
Ex py intro-20100630Ex py intro-20100630
Ex py intro-20100630
 
曖昧 RPM 講座
曖昧 RPM 講座曖昧 RPM 講座
曖昧 RPM 講座
 

Pythonと型チェッカー

  • 2. 自己紹介 ● 森本 哲也 – twitter: @t2y ● ポータルサイトの会社 – オブジェクトストレージの開発・運用 ● 業務では Go 言語で開発 – 普段使いのツールやプロトタイピングに Python ● エキスパート Python プログラミング改訂2版 – Python 3.5 ( 翻訳は 3.6) を対象
  • 3. 最近のニュース ● Pyre: Fast Type Checking for Python – 概要から引用 Facebook 社も Instagram 社も大規模に Python を使っています。私たちは Python の表現力、 柔軟性、開発における生産性をとても好んでいます。しかし、数百万行といった大規模コード ベースの保守を考えると、そういった良いところにも陰りがみえてきます。 ● 静的な保証がないと、既存のコードベースを安全に変更することが難しくなり、コードのエラーが発生しや すくなって静的型付けされたコードと比べて開発が遅くなる ● コード検索、コード補完、ナビゲーション、リファクタリングサポートなどの高品質なツールを構築するこ とが難しい。こういったツールがないと、大規模コードベースで作業するときに特に弊害となる これらの問題に対処するために、私たちは高速な PEP 484 互換の型チェッカーと深い静的解析 ツールを構築するための優れたプラットフォームの双方を兼ね備えた Pyre を構築しました。
  • 4. 型ヒント付きコードのサンプル import json import sys from pprint import pformat from typing import Any, Dict def pretty_format(data: Dict[str, Any]) -> str: return pformat(data, width=1) def main(raw_data: str) -> None: data = pretty_format(json.loads(raw_data)) data.append('mypy') # error: "str" has no attribute "append" if __name__ == '__main__': raw_data: str = sys.argv[1] main(raw_data)
  • 6. これまでの経緯 ● Python 3.5 リリース – PEP 484 型ヒント→ typing モジュールを提供 – mypy-lang 0.2.0 (2015-04-06) ● Python 3.6 リリース – PEP 526 変数アノテーション – mypy 0.470 (2017-01-13) ● いま – mypy 0.600 (2018-05-02) ● Python 3.7 予定 2015-09-13 2016-12-23 2018-06-15 この資料で 扱う範囲
  • 7. 最近の mypy のリリース履歴 ● 0.600: mypy daemon ● 0.590: 型情報のパッケージングを試験導入 (PEP561) ● ... ● 0.530: structural subtyping を試験導入 (PEP544) ● 0.510: ClassVar サポート ● ... ● 0.470: pypi のパッケージ名を mypy-lang から mypy へ移行 ● (mypy-lang) 0.4 2017-01-13 2018-05-02 2017-10-06 2018-04-13 Python の開発スケジュールと並行して mypy に機能を試験導入している
  • 8. Python への機能追加の流れ 1. サードパーティでやってみよ mypy の開発は 2012 年開始 (Python3.2/3.3) 2. 標準ライブラリに入れましょう 型ヒントは typing モジュールとして提供 (Python3.5) 3. C 言語拡張でなんとかしましょう typed_ast: 型コメントを扱える / 高速 ast ライブラリ 4. 言語に変更を加えましょう (Python3.6/3.7 PEP 526/560) Python のコア機能の拡張は保守的に進められる 新規の機能がいきなり言語のコアに入ることは基本的にない イマココ!
  • 10. mypy daemon ● mypy 0.600 でサポート – まだ beta レベル ● 数ファイル変更したときに毎回 mypy を実行す るのはパフォーマンスがよくない ● dmypy を使うと大規模なコードベースでは mypy コマンドと比べて数十倍速いらしい
  • 11. mypy command $ time mypy --no-incremental sphinx real 0m21.968s user 0m20.986s sys 0m0.769s $ time mypy --follow-imports=error sphinx sphinx/events.py: note: In member "disconnect" of class "EventManager": sphinx/events.py:71:5: error: Missing return statement real 0m16.784s user 0m16.366s sys 0m0.361s
  • 12. mypy daemon $ dmypy start -- --follow-imports=error Daemon started $ ps ax|grep dmypy 59452 ?? S 0:00.00 path/to/dmypy start -- --follow-imports=error $ time dmypy check sphinx real 0m20.714s user 0m0.116s sys 0m0.035s $ time dmypy check sphinx Daemon crashed! Traceback (most recent call last): ... AttributeError: 'NoneType' object has no attribute 'type_vars' エラーになって計測できなかった。。。
  • 13. TypedDict(1) ● mypy_extensions の拡張機能 – 試験的機能だが、 mypy 0.530 から公式サポート ● 厳密なディクショナリの型定義 – 特定の key のみに限定したいとき – value の型が複数あるようなとき – すべての要素を指定させたいとき
  • 14. TypedDict(2) from typing import Dict, Any, Union blade_runner: Dict[str, Any] = {'name': 'Blade Runner', 'year': 1982} toy_story: Dict[str, Union[str, int]] = {'name': 'Toy Story', 'year': 1995} from mypy_extensions import TypedDict Movie = TypedDict('Movie', {'name': str, 'year': int}) blade_runner: Movie = {'name': 'Blade Runner', 'year': 1982} toy_story = Movie(name='Toy Story', year=1995) Movie はコンストラクタとしても使える TypedDict を関数の引数に渡したときは型アノテーションはか 書かなくても mypy が型推論する
  • 15. TypedDict(3) name, year が定義されていないと型チェックでエラーになる total=False を渡すとエラーにならない the_rock = Movie(name='The Rock') # error: Key 'year' missing for TypedDict "Movie" Movie = TypedDict('Movie', {'name': str, 'year': int}, total=False) the_rock = Movie(name='The Rock')
  • 16. TypedDict(4) 3.6 からクラス構文でも定義できる クラスだと型定義を継承することもできる from mypy_extensions import TypedDict class Movie(TypedDict): name: str year: int blade_runner: Movie = {'name': 'Blade Runner', 'year': 1982} class ExtraMovie(Movie): director: str the_rock = ExtraMovie(name='The Rock', year=1996, director='Michael Bay')
  • 17. NamedTuple(1) ● TypedDict 同様に 3.6 からクラス構文をつかっ た NamedTuple の定義ができる
  • 18. NamedTuple(2) from collections import namedtuple Point = namedtuple('Point', ['x', 'y']) p = Point(x=1, y=2) print(p.z) # Error: Point has no attribute 'z' from typing import NamedTuple Point = NamedTuple('Point', [('x', int), ('y', int)]) p = Point(x=1, y='x') # Error: Argument has incompatible type "str"; expected "int"
  • 19. NamedTuple(3) from typing import NamedTuple class Point(NamedTuple): x: int y: int p = Point(x=1, y='x') # Error: Argument has incompatible type "str"; expected "int" 3.6 からクラス構文でも定義できる NamedTuple の型定義は継承できない
  • 20. NewType(1) ● typing に 3.5.2 で追加 ● 論理的なエラーチェックのためにクラスを生成 すると実行時オーバーヘッドになる ● クラスを生成せずに型チェックできるヘルパー 関数を提供
  • 21. NewType(2) class UserId(int): pass def name_by_id(user_id: UserId) -> str: ... from typing import NewType UserId = NewType('UserId', int) UserId('user') # error: Argument 1 to "UserId" has incompatible type "str"; expected "int" name_by_id(42) # error: Argument 1 to "name_by_id" has incompatible type "int"; expected "UserId" name_by_id(UserId(42)) # OK num = UserId(5) + 1 # type: int
  • 22. NewType の実装 def NewType(name, tp): """NewType creates simple unique types with almost zero runtime overhead. NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns a dummy function that simply returns its argument. Usage:: """ def new_type(x): return x new_type.__name__ = name new_type.__supertype__ = tp return new_type
  • 23. ソースファイルのオーバーロード ● 当初 PEP 484 では @overload デコレーターは スタブファイルのみでのサポートと記述されて いたが、その制約は見直された – Relax constraints on @overload. It may occur in modules if followed by a non-@overload version. ● ソースコードにも記述して mypy で型チェック できるようになった ● Union 型では厳密に定義できないときがある ● mypy 0.510 でサポート
  • 24. リストの添字アクセス (Union) from typing import Sequence, TypeVar, Union T = TypeVar('T') class MyList(Sequence[T]): def __getitem__(self, index: Union[int, slice]) -> Union[T, Sequence[T]]: if isinstance(index, int): ... # Return a T here elif isinstance(index, slice): ... # Return a sequence of Ts here else: raise TypeError(...) リストの添字アクセス - インデックス値かスライスを指定したら T か Sequence[T] を返す
  • 25. リストの添字アクセス (overload) リストの添字アクセス - インデックス値を指定したら T を返す - スライスを指定したら Sequence[T] を返す from typing import overload, Sequence, TypeVar, Union T = TypeVar('T') class MyList(Sequence[T]): @overload def __getitem__(self, index: int) -> T: pass # Don't put code here @overload def __getitem__(self, index: slice) -> Sequence[T]: pass # Don't put code here
  • 27. デコレート関数の型チェック from typing import TypeVar, Callable, Any, cast T = TypeVar('T', bound=Callable[..., Any]) def logged(description: str) -> Callable[[T], T]: def decorator(f: T) -> T: def wrapper(*args, **kwargs): print('entering:', description) value = f(*args, **kwargs) print('leaving:', description) return cast(T, wrapper) return decorator @logged('system initialization') def init() -> None: print('do something') init(1) # error: Too many arguments (signature is correctly preserved)
  • 28. Metaclass ● シンプルな metaclass の型チェク ● mypy0.501 でサポート class Meta(type): def __add__(self, x: str) -> str: return 'a' + x class C(metaclass=Meta): ... print(C + 'x') # Okay print(C + 1) # error: Unsupported operand types for + ("Type[C]" and "int")
  • 31. 型ヒント関連の PEP の履歴 ● PEP 484 型ヒント – Nominal Subtyping の型チェックのみ ● PEP 526 変数アノテーションの構文 – Structural Subtyping に必要 ● Python 3.7 – PEP 560 typing モジュールとジェネリック型のコアサポート – PEP 563 アノテーションの評価の延期 – PEP 544 プロトコル : Structural Subtyping – PEP 561 型情報のパッケージング Python 3.5 Python 3.6 ( 承認 ) ( 承認 ) 延期 延期 mypy support
  • 32. PEP 560 typing モジュールと ジェネリック型のコアサポート ● typing モジュールのジェネリック型の様々な問題 – 実行時オーバーヘッド – メタクラスの競合 – メタクラスハックによるバグの温床 ● 2 つの特殊メソッドを追加 – __class_getitem__: クラスの添字のときに呼ばれる – __mro_entries__: クラス定義の親リストにクラスオブ ジェクトではないものが指定されたときに呼ばれる
  • 33. クラスの添字を扱うメタクラス class MetaSubscript(type): def __new__(cls, name, bases, namespace, **kwds): return super().__new__(cls, name, bases, dict(namespace)) def __getitem__(cls, params): cls.params = params return cls.__class__(cls.__name__, cls.__bases__, cls.__dict__) class MyGeneric(metaclass=MetaSubscript): pass g = MyGeneric[str]() print(MyGeneric.params) # <class 'str'> クラスの作成時に metaclass.__new__ が呼ばれる 例えば、型アノテーションのためにクラスを インポートしたときにオーバーヘッドになってしまう
  • 34. PEP 563 アノテーションの評価の先送り ● 関数定義時点でアノテーションが評価されること による問題 – 前方参照ができない – インポート時に型ヒントが実行される ● アノテーションを評価しないオプション – Python 4.0 からデフォルトになる from __future__ import annotations
  • 35. 前方参照のコード例 class A: def f(self): return B() b = B() # NameError: name 'B' is not defined def f(): b = B() f() # NameError: name 'B' is not defined a = A() a.f() # NameError: name 'B' is not defined class B: pass
  • 36. 前方参照の型アノテーション ( 型アノテーションのみサポート ) from __future__ import annotations class C: field = 'c_field' def method(self) -> C.field:... # this is OK def method(self) -> field:... # this is OK def method(self) -> C.D:... # this is OK def method(self) -> D:... # this is OK class D: field2 = 'd_field' def method(self) -> C.D.field2:... # this is OK def method(self) -> D.field2:... # this is OK def method(self) -> field2:... # this is OK def method(self) -> field:... # this FAILS, class D doesn't # see C's attributes, This was # already true before this PEP.
  • 37. PEP 544 プロトコル : Structural Subtyping ● 別名 : 静的なダックタイピング ● 型ヒントの大きなマイルストーン? ● https://github.com/python/typing/issues/11 – 作成日 :2014-10-16 (3.5 のリリース前 ) – 型ヒントが導入される以前から議論されていた – 3.7 で提案されたが、残念ながら延期された ● Python プログラマーにとって、より自然なセマ ンティクスで型アノテーションを書ける 37
  • 38. ダックタイピング ● 型の安全性における duck test を満たすアプリ ケーションをダックタイピングと呼ぶ – duck test とは、論理的推論方法 ( 帰納法 ) の一種 – " もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである " ● 型チェックを実行時に遅延させる – 動的型付けやリフレクションを用いて実装される ● ダックタイピングは オブジェクトのメソッドや プロパティの有無で決定される def talk(x, y): x.greet(y.name)
  • 39. 2 つのクラスが型として互換か ● Nominal Subtyping ( 名前的部分型 ) – クラスを定義してクラス階層で部分型が成立する – 継承によって実現する ● Structural Subtyping ( 構造的部分型 ) – すべての属性 ( プロパティ ) とメソッドをもっている なら部分型が成立する – mypy は Protocol クラスを介してサポートする from typing_extensions import Protocol ダックタイピングと似ている!
  • 40. Nominal Subtyping ( 名前的部分型 ) from typing import Sized, Iterable, Iterator class Bucket(Sized, Iterable[int]): def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... def collect(items: Iterable[int]) -> int: len(items) result: int = collect(Bucket()) # Passes type check
  • 41. Structural Subtyping ( 構造的部分型 ) from typing import Iterator, Iterable class Bucket: def __len__(self) -> int: ... def __iter__(self) -> Iterator[int]: ... def collect(items: Iterable[int]) -> int: len(items) result: int = collect(Bucket()) # Passes type check
  • 42. 抽象基底クラス (ABC) from abc import ABCMeta, abstractmethod class InterfaceGreet(metaclass=ABCMeta): @property @abstractmethod def name(self): ... @abstractmethod def greet(self, other): ... class Person(InterfaceGreet): name = '' p = Person() # error: Cannot instantiate abstract class # 'Person' with abstract attribute 'greet' これまでのやり方 Python でインターフェースっぽいもの
  • 43. ユーザー定義プロトコル (1) from typing_extensions import Protocol class Greetable(Protocol): name: str def greet(self, other: str) -> None: ... class Person: def __init__(self, name: str) -> None: self.name = name p: Greetable = Person(' もりもと ') # error: Incompatible types in assignment # (expression has type "Person", variable has type "Greetable") # note: 'Person' is missing following 'Greetable' protocol member: # note: greet Greetable を継承しなくて良い!
  • 44. ユーザー定義プロトコル (1) from typing_extensions import Protocol class Greetable(Protocol): name: str def greet(self, other: str) -> None: ... class Person: def __init__(self, name: str) -> None: self.name = name def greet(self, other: str) -> None: print(' こんにちはー {}'.format(other)) class Cat: def __init__(self, name: str) -> None: self.name = name def greet(self, other: str) -> None: print(' にゃあー {}'.format(other)) def greet_each_other(x: Greetable, y: Greetable) -> None: x.greet(y.name) y.greet(x.name) def main() -> None: morimoto = Person(' もりもと ') tama = Cat(' たま ') greet_each_other(morimoto, tama)
  • 45. ユーザー定義プロトコル (2) class Anonymous: def greet(self, other: str) -> None: print(' やあ {}'.format(other)) def greet_each_other(x: Greetable, y: Greetable) -> None: x.greet(y.name) y.greet(x.name) def main() -> None: morimoto = Person(' もりもと ') anonymous = Anonymous() greet_each_other(morimoto, anonymous) # error: Argument 2 to "greet_each_other" has incompatible type "Anonymous"; expected "Greetable" # note: 'Anonymous' is missing following 'Greetable' protocol member: # note: name エラーメッセージもわかりやすい
  • 46. PEP 561 型情報のパッケージング ● mypy は mypy を実行する python インタープリ ター向けにインストールされたパッケージディレ クトリから型情報を含むパッケージを探索する – 複数の仮想環境を扱うときなどうまくいかない ● 型情報を配布するパッケージングの仕組み 1.コード内に型アノテーションを記述している 2.実行コードと一緒に型情報の stub を提供する 3.型情報の stub を独立したパッケージで提供する
  • 47. コード内に型アノテーションを記述 setup.py package_a/ __init__.py lib.py py.typed from distutils.core import setup setup( name="SuperPackageA", author="Me", version="0.1", package_data={"package_a": ["py.typed"]}, packages=["package_a"] ) py.typed を作る
  • 48. 実行コードと一緒に 型情報の stub を提供する setup.py package_b/ __init__.py lib.py lib.pyi py.typed from distutils.core import setup setup( name="SuperPackageB", author="Me", version="0.1", package_data={"package_b": ["py.typed", "lib.pyi"]}, packages=["package_b"] ) py.typed と lib.pyi を作る
  • 49. 型情報の stub を独立した パッケージで提供する setup.py package_c-stubs/ __init__.pyi lib.pyi from distutils.core import setup setup( name="SuperPackageC", author="Me", version="0.1", package_data={ "package_c-stubs": ["__init__.pyi", "lib.pyi"] }, packages=["package_c-stubs"] ) __init__.pyi と lib.pyi を作る
  • 52. mypy プロジェクト (1) ● http://mypy-lang.org/ ● Python 本体は型ヒントの構文のみを標準化 – 標準ライブラリとして typing モジュールを提供 ● 型チェッカーはサードパーティ – mypy は型チェッカーの参照実装のようなもの – https://github.com/python/mypy ● リポジトリは python organization 配下にある ● コミュニケーション (ML ではなく Gitter) – https://gitter.im/python/typing
  • 53. mypy プロジェクト (2) ● コア開発者 – Jukka Lehtosalo: mypy 作者 (@Dropbox) – Guido van Rossum: python 作者 (@Dropbox) – David Fisher: (@Dropbox) – Ivan Levkivskyi: 理論物理学 (@University of Bern) – Elazar Gershuni: (@Technion) – Michael J. Sullivan: (@Dropbox) ● 直近でコントリビュートしている上位開発者 Dropbox 社が強い関心をもっているのがわかる
  • 54. mypy プロジェクト (3) ● mypy_extensions – https://pypi.org/project/mypy_extensions/ ● コードは mypy リポジトリの内部にある – https://github.com/python/mypy/tree/master/exte nsions ● mypy の試験的な機能や拡張を提供 – TypedDict( 後述 ) を使うときに必要 ● Mypy 0.530 Released
  • 55. typing プロジェクト (1) ● https://github.com/python/typing – typing モジュールの開発や議論 – 当初の予定では 3.5.0 から 3.7.0 までだった? ● 3.7.0 で typing モジュールの“ provisional" を外す予定 – https://github.com/python/typing/issues/495#i ssuecomment-342644111 ● typing を標準ライブラリから外すかどうかの議論 ● 少なくとも 3.7.0 では“ provisional" にしよう
  • 56. typing プロジェクト (2) ● コア開発者 – Guido van Rossum: python 作者 (@Dropbox) – Ivan Levkivskyi: 理論物理学 (@University of Bern) – Łukasz Langa: (@Facebook) – Andrey Vlasovskikh: (@JetBrains) – Jukka Lehtosalo: mypy 作者 (@Dropbox) ● コントリビュートの上位 5 人 mypy/typing ともに Guido 氏がイニシアティブをもって取り組んでいる
  • 57. typing プロジェクト (3) ● typing_extensions – https://pypi.org/project/typing-extensions/ ● コードは typing リポジトリの内部にある – https://github.com/python/typing/tree/master/ty ping_extensions ● typing の試験的な機能や型を提供 ● 旧バージョン (3.5/3.6) のバックポートとしても 使える Protocol は typing_extensions からインポートできる
  • 58. typeshed リポジトリ ● https://github.com/python/typeshed – 型チェックのための stub 共有リポジトリ – TypeScript でいうところの DefinitelyTyped ● 標準ライブラリの stub を提供 ● サードパーティはまだ少し – 追加するには対象ライブラリのメンテナーに連絡し て許可を得る
  • 59. typed_ast プロジェクト ● https://github.com/python/typed_ast – mypy の依存パッケージとしてインストールされる – Python2.7/3 向けのパーサーを提供する – 標準 ast ライブラリと完全互換 ● 型コメントを扱える ● 標準 ast のバグは直さない (upstream で修正しない限り ) – 標準 ast よりも高速らしい
  • 61. Cython と型アノテーション ● Pure Python Mode – Python 文法の範囲内でコードを記述 – 最適化したいところだけでコレータを付与 – 型ヒントの構文で Cython の型情報を記述 from ctypes import c_char, POINTER # Before def feeder(c_string): cdef char* c_string = NULL # After def feeder(c_string: POINTER(c_char)) -> None: pass
  • 62. 型アノテーションの自動生成 ● PyAnnotate (@Dropbox) – https://github.com/dropbox/pyannotate – Python2/3 向け、型コメントを生成 ● MonkeyType (@Instagram) – https://github.com/Instagram/MonkeyType – Python3 向け、 stub/ 型アノテーションを生成 ● リファレンス – Python の型アノテーションを自動生成する ● PyAnnnotate と MonkeyType の調べてみた
  • 63. その他の型チェッカー ● PyCharm: Type Hinting in PyCharm – PEP 563 アノテーションの評価の延期 – 型ヒントや変数アノテーションのサポート – Typeshed との連携 ● Pyre: https://pyre-check.org/ – 高速でスケーラブルな型チェッカー
  • 65. 型ヒントの成功の兆し? ● typing/mypy の開発は十分に活発にみえる – パフォーマンスについて懸念されるようになった – 型ヒント関連の PEP も継続的に提案されている ● 大規模なコードベースをもつ企業での運用 – Dropbox/Zulip ● ノウハウやツールを公開 ● Guido, Jukka 氏も活発に開発 – Facebook/Instagram ● エディタや CI 連携を考慮した 実務的な型チェッカーやライブラリを公開 今後の実運用からの フィードバックも 期待される
  • 66. typing は 3.8 で stable ? ● 3.5 で型ヒントを導入したとき – 賛否両論で議論が盛り上がった – 3.7 で provisional→stable の予定だったが延期 – それでも開発は活発にみえる ● 3.8 の期待 – Structural Subtyping がサポートされるはず – mypy は先行サポートしているので待つ必要はない
  • 67. 今後のサードパーティの対応? ● typeshed にはまだまだ少ない – スタブのメンテはしんどいよね ● よく使われているサードパーティがどのぐらい 対応していくか – 2020 年の Python2 のサポート終了 – 2/3 対応から 3 のコードベースへ移行? ● 型アノテーションの自動生成の未来 – いまツールが公開されたところ
  • 69. Python 開発 ● Python ドキュメント – What’s New In Python 3.7 – typing — 型ヒントのサポート ● DSAS 開発者の部屋 – 最近のPython-dev(2017-12) – 最近のPython-dev(2017-06) – 最近のPython-dev (2017-05) ● 言語設計者たちが考えること O'Reilly Japan, Inc.
  • 70. 型ヒント ● What is Gradual Typing: 漸進的型付けとは何か ● PEP – [翻訳] PEP 0484 -- 型ヒント (Type Hints) ● Python と型ヒント (Type Hints) と #pyconjp – PEP 526 -- Syntax for Variable Annotations – PEP 544 -- Protocols: Structural subtyping (static duck typing) – PEP 560 -- Core support for typing module and generic types – PEP 561 -- Distributing and Packaging Type Information – PEP 563 -- Postponed Evaluation of Annotations ● [翻訳] Python の静的型、すごい mypy!
  • 72. その他のツール ● Cython: Python Typing Proposal ● Dropbox releases PyAnnotate -- auto-genera te type annotations for mypy ● Dropbox releases mypy-protobuf ● Let your code type-hint itself: introducing open source MonkeyType ● Pycon2017 instagram keynote ● スライド内のサンプルコード – https://github.com/t2y/python-study/tree/mas ter/MiniOsaka