20170131 python3 6 pep526

Post on 07-Feb-2017

484 Views

Category:

Engineering

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

pep 526 and 周辺ツールについて2017/01/31 Python 3.6 Release Party @Yahoo!Japan

自己紹介

@Masahito

github: masahitojp

株式会社ヌーラボ所属

主に Scala(be�er Java) とJSと少々のPythonでご飯を食べています

近頃はmypyとGrumPyがお気に入り

今日話すことPEP 526 - Syntax for Variable Annotations

typing module

周辺ツール、特にmypy

PEP 526‐ Syntax for VariableAnnota�ons

PEP 526はPEP484 の拡張です。

PEP 484 ‐ Type Hint ご存知のかた?

PEP 484についてPEP-484 Type Hint(en)

@t2y さんの日本語訳も提供されてます

PEP-484 Type Hint(ja)

PEP484について軽く説明PEP 3107 Function Annotations ってのがPythonに入ってPythonの関数に、任意のメタデータを追加するための構文を導入する

def compile(source: "something compilable", filename: "where the compilable thing comes from", mode: "is this a single statement or a suite?"):

PEP3107 では特に意味づけがなかったものを Type Hint として使おうっていうのがPEP484です

def greeting(name: str) -> str: return 'Hello ' + name

PEP484の目的としないものPython は依然として動的型付け言語のままです。 Python の作者たちは(たとえ規約としてであっても)型ヒントを必須とすることを望んではいません。

この方針はPEP526でも同じです。

じゃーなにが追加になったの?

変数に対して型付けする構文が追加になった

from typing import List

# pep 484a = [1,2,3] # type: List[int]

# We should add *comments*path = None # type: Optional[str] # Path to module source

# pep 526a: List[int] = [1,2,3]path: Optional[str] = None # Path to module sourde

値を指定しなくてもよい

# pep 484child # type: bool # これはゆるされない

# pep 526child: bool # こちらはokif age < 18: child = Trueelse: child = False

これは全部同じ意味になる

# 3.6でもpep484スタイルを許す(後方互換性!hour = 24 # type: int

# 値を指定せずに定義して代入hour: int; hour = 24

hour: int = 24

variable annota�on はどこに格納される?

__annotaitons__ に格納される

>>> answer:int = 42>>> __annotations__{'answer': <class 'int'>}

クラス変数のみ格納される、インスタンス変数は無視される

>>> class Car:... stats: ClassVar[Dict[str, int]] = {}... def __init__(self) -> None:... self.seats = 4>>> c: Car = Car()>>> c.__annotations__{'stats': typing.ClassVar[typing.Dict[str, int]]}# only ClassVar!

こんな書き方をしてもPythonとしてはゆるしてくれる

>>> alice: 'well done' = 'A+' # >>> bob: 'what a shame' = 'F-'>>> __annotations__{'alice': 'well done', 'bob': 'what a shame'}

けどPEP526ではType Hintとしてつかうことを推奨する

typing

typing moduleとはPython 3.5でPEP484が実装された時に入ったモジュール

DictとかTupleとかListみたいなbuild inのものはすでにこのモジュールで定義されている

from typing import Dict, Tuple, List

ConnectionOptions : Dict[str, str]Address : Tuple[str, int]Server : Tuple[Address, ConnectionOptions]

もちろんドキュメントも https://docs.python.org/3/library/typing.html

pip install typing python2でもつかえる, mypyのpy2modeを使うときに実は使います

typing moduleの変更点

Collection

ContextManager

withで実行されるような型

class Context(object):

def __init__(self): print '__init__()'

def __enter__(self): print '__enter__()' return self def __exit__(self, exc_type, exc_val, exc_tb): print '__exit__()'

NamedTuple

Point = namedtuple('Point', ['x', 'y'])p = Point(x=1, y=2)print(p.z) # Error: Point has no attribute 'z'

Python 3.6 で以下のようにかけるようになった

from typing import NamedTuple

class Point(NamedTuple): x: int y: int

周辺ツール

周辺ツール静的型チェッカー

っていうと難しく感じるかもですが要はコマンドです

mypy

pytype

IDE

PyCharm(今回は割愛

pytypegoogleのリポジトリで開発されてる

Matthias Kramm(さんが一人でやってるっぽい

https://github.com/google/pytype

いまはPython2.7でのみ動く

けど、3.4/3.5モードで動かして型チェックすることも可能

pytype -V 3.5 program.py

PEP526のチェックもmasterブランチでは実装されてるが、いまのところ3.6モードはない

Magic Exceptionがでる

mypypythonのレポジトリで開発されている

https://github.com/python/mypy

JukkaLさんが中心になって作成

今回は静的型チェッカーとしてのmypyについて話します

最近パッケージ名が変わった  mypy-lang -> mypy

こちらはすでに3.6モードが実装済み

じつはcobertruaで吐き出すモードがあったりとCIにつっこむと嬉しいオプションもあります

mypyfrom typing import Dict, NamedTuple

class Car: stats: Dict[str, int] = {} def __init__(self) -> None: self.seats = 4 class Employee(NamedTuple): name: str id: int

c: Car = Car()# print(c.__annotations__)employee = Employee(name='Guido', id='x')

mypy --fast-parser --python-version 3.6 example.pyexample.py:16: error: Argument 2 to "Employee" has incompatible type "str"; expected

typeshed について軽く

TypeScriptでいうところのDe�nitely TypedのPython版

mypy/pytypeはこれを利用しています

つまりこれに対応していないモジュールは実行するとエラーになります

現状(py36-mypy)~/s/p/try-pep526> cat collection.py

from typing import Collection

a: Collection[int] = [3,2,1]a.append(1)

(py36-mypy)~/s/p/try-pep526> mypy --fast-parser --python-version 3.6 collection.collection.py:2: error: Module 'typing' has no attribute 'Collection'

typeshedとtypingモジュールの状況

typeshedのtypingモジュールは3.5までしか対応してません  orz

そのため, いかのモジュールをimportすると定義されてないよエラーが

typing.ClassVar -> PEP526に書かれてるんだけどなぁ。。。。

https://github.com/python/typeshed/pull/889 無事近頃ttypeshedにはとりこまれた模様

typing.Collection -> Listとかで代用

typing.CotextManager -> ...

一応自分で定義(.ipr)をつくると行けそう

mypy for Python 3.6構文追加系は動くのでぜひ使ってみるといいのではhttp://mypy.readthedocs.io/en/latest/python36.html

動く

PEP526対応済み(ただしClassVarはまだ

Underscores in numeric literals (PEP 515) e.g. million = 1_000_000

NamedTuple

未実装

Asynchronous generators (PEP 525)

Asynchronous comprehensions (PEP 530)

mypy for Python3.6typeshedが対応すれば動くはず

typingで追加されたもの

時間が余ったとき用

typingにはじつは _Protocol ってのが存在してる

Protocols (a.k.a. structural subtyping)要はこんな感じであるメソッドが実装されている型を新しくつくれるといいねっていう提案、mypy作者とGuido(!)を中心に議論

class Sized(Protocol): @abstractmethod def __len__(self) -> int: pass # __len__は特殊メソッド def hoge(l : Sized) -> int: return len(l) + 1

PEP 526が入ったことでこういうのもProtocolっぽく動くよねっていう議論が

class Point(<some magical base class): x: float y: float z: float = 0

class MyPoint: # unrelated to Point def __init__(self, x: float, y: float): self.x, self.y = x, yp = MyPoint(1, 2)

とこんな感じでまだ固まってないので typing.Protocol が使えるのはまだ先のようです。(typingの内部では使われているので興味ある方は読んでみるとよいかと)

まとめ

PEP526で変数名にType Hintつけるのが楽になった

typingモジュールもだんだん進歩している

ぜひ mypy とかを使っていただいて、  みんなで typeshed を育てていきましょう

top related