SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
Python と型ヒント
2015-10-10 Tetsuya Morimoto
自己紹介
●
森本 哲也
– twitter: @t2y
●
白ヤギコーポレーション所属
– カメリオAPI開発 ( 興味がある方はブースへ )
●
エキスパート Python プログラミング共訳
●
プログラミング言語歴
– Python (3 年 )
– → Java (3 年 )
– → Go ( 半年 )
求人
●
自然言語処理や機械学習の技術を駆使して製品
開発をしたい人募集!
Pythonのパラドックス
●
2004 年 8 月 Paul Graham
– Python を学ぼうとするプログラマーは賢い
●
Python 2.3.4 (2004-05-27): 2.3 の時代
– 新しい言語を学ぶ人たちはプログラミングが好き
であり、仕事に役立つから学ぶわけではない
– 曲解 : 「優秀な Java プログラマーを採用したかっ
たら Python プログラマーを雇えば良い」
●
いまは成り立たない
Python3 のパラドックス
●
2015 年 10 月
– Python3 を現場に導入しようとするプログラマーは
賢い
– Python3 を導入する人たちはプログラミングが好き
であり、現場で役立つから導入するわけではない
– 曲解 : 「優秀な Python プログラマーを採用した
かったら Python3 を現場に導入すれば良い」
●
それっぽい? ( 自己責任で! )
概要
●
背景
– 漸進的型付け→関数アノテーション→ mypy
●
PEP 484 〜型ヒント〜
– 目的
– 型ヒントのために定義された型 (Any, Union, etc)
– ジェネリクス
●
懸念
– 型ヒントの批判、 Typed Clojure の現在
●
展望
– 構造的部分型 (Structual Subtyping) へ
Python3.5
背景
背景 : 漸進的型付け (Gradual Typing)
●
Jeremy Siek 氏と Walid Taha 氏が 2006 年に
考案した型システム
– 静的型付けと動的型付けを組み合わせられる
– 双方の型システムの良いとこ取りしたもの
– Object 型ではなく Any 型を導入しなければならな
い背景の説明
●
PEP 484 の理論的背景
●
入門記事 : 漸進的型付けとは何か
背景 : 関数アノテーション (PEP3017)
●
Python3.0 で導入 (PEP3017)
– 2008-12-03 リリース
– 関数に任意のアノテーションを書く仕組み
●
PEP 484 を支える基本的な仕組み
– 関数アノテーションの用途を型アノテーションに
限定した
– 関数オブジェクトの __annotations__ 属性に保持
されるのは同じ
背景 :mypy プロジェクト (1)
●
http://mypy-lang.org/
●
作者 : Jukka Lehtosalo 氏
– プログラマーを 6 年、マネージャーを 2 年
– 2009 年からケンブリッジ大学の博士課程
●
2012 PyCon Finland
– MYPY: A PYTHON VARIANT WITH SEAMLESS DYNA
MIC AND STATIC TYPING
●
静的型付けと動的型付けの融合
– PyPy や Cython がライバル、 GIL のない VM
背景 :mypy プロジェクト (2)
●
現時点の mypy ができること
– GIL のない VM
– 型アノテーション→ PEP 484 で標準化
– 静的型チェッカーとしての Lint ツール
●
PEP 484 では型チェッカーは提供しない
PEP 484
型ヒント
型ヒント : サンプルコード
# -*- coding: utf-8 -*-
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() -> None:
raw_data = sys.argv[1] # type: str
data = pretty_format(json.loads(raw_data))
print(data)
data.append('mypy')
main()
$ mypy tutorial.py
tutorial.py: note: In function "main":
tutorial.py:14: error:
"str" has no attribute "append"
型ヒント : 目的
●
型アノテーションの構文を標準化
●
静的解析
– Lint ツール ( オフライン型チェッカー )
●
IDE
– コード補完やリファクタリング機能に利用
– Type Hinting in PyCharm
●
ドキュメンテーション
– 型アノテーションがそのまま使える?
Python は
動的型付け言語
型ヒント :Sphinx
俺がやる!
型ヒント :Any 型
●
全ての型は Any 型のサブタイプ
– object 型と似ているが、型チェッカーによる扱い
が異なる
●
object 型
– 型チェッカーは値のほとんどの操作を拒否する
●
Any 型
– 型チェッカーは値の全ての操作を許容する
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 型の操作は型チェカーでエラーとなる
理論的背景は「漸進的型付けとは何か」を参照
型ヒント : 直和型 (Union Type)
●
直和型
– 関数型プログラミング言語でよく使われるデータ型
– 典型的にはツリーのデータ構造を簡潔に表現できる
●
単一の引数に対して少数の期待される型の集合
をとる
e = Union[Employee, Sequence[Employee]]
# OCaml バリアント型
type day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
# 第7回「代数データ型」でいろいろなデータを表してみる
型ヒント :Optional 型
●
直和型の応用
●
Union[T1, None] と Optional[T1] は等価
– None を取り得ることが明示される
– None は多くの操作が型エラー
●
Java の NullPointerException はこりごり
– @Nonnull, @Nullable のアノテーションを明示
– Collections.emptyList(), Collections.emptyMap()
●
Null 安全を型システムで保証する世界へ
型ヒント :Optional 型の例
from typing import Optional, Union
def func1(data: Optional[int]) -> int:
return 3 + data
def func2(data: Union[int, None]) -> int:
return 3 + data
def func3(data: int=None) -> int:
return 3 + data
これらは等価な型ヒント
・デフォルト引数に
None を指定したときも
Optional 型として扱う
TypeError: unsupported operand type(s) for +:
'int' and 'NoneType'
型ヒント : ジェネリクス
●
コンテナー内の要素に期待する型を示す
●
TypeVar というファクトリーを使って型変数を
定義する
from typing import Sequence, TypeVar
T = TypeVar('T') # Declare type variable
def first(l: Sequence[T]) -> T: # Generic function
return l[0]
型ヒント :TypeVar
●
TypeVar のコンストラクタに渡す型変数を表す
文字列と代入する変数名は同じでなければいけ
ない
from typing import TypeVar
X = TypeVar('X') # correct
Z = TypeVar('Y') # error
mypy
generics_typevar.py:4: error: Unexpected TypeVar() argument value
型ヒント :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)
型の別名
型ヒント : 型別名と直和型
●
型別名と直和型の違い
– 型パラメーターとなり得るか
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[...]
型ヒント : ユーザー定義ジェネリック型
●
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)
型ヒント : 型消去
●
ユーザー定義のジェネリック型はインスタンス
化できる
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]
型ヒント : 数値型階層 (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"
型ヒント : スタブファイル
●
型チェッカーのための拡張モジュール
●
型ヒントを Python モジュールではなく外部の
ファイルに書き出すためのもの
●
拡張子は .pyi
●
主には ( 型ヒントがない ) サードパーティのラ
イブラリと一緒に型ヒントを使うため
– スタブを集める typeshedリポジトリもある
●
TypeScript でいうところの DefinitelyTyped
型ヒント : スタブの例
class tzinfo:
def tzname(self, dt: Optional[datetime]) -> str: ...
def utcoffset(self, dt: Optional[datetime]) -> int: ...
def dst(self, dt: Optional[datetime]) -> int: ...
def fromutc(self, dt: datetime) -> datetime: ..
class timezone(tzinfo):
utc = ... # type: tzinfo
min = ... # type: tzinfo
max = ... # type: tzinfo
def __init__(self, offset: timedelta, name: str = '') -> None: ...
def __hash__(self) -> int: ...
datetime.pyi
型ヒント : その他
●
呼び出し可能オブジェクト
●
抽象ジェネリック型
●
上界をもつ型変数
●
共変性と反変性
●
前方参照
●
キャスト
●
...
PEP 484 を読んでください ...
懸念
懸念 :(Python に ) 必要か?
●
Python に型ヒントは本当に必要なのか?
●
Revenge of the Types: 型の復讐 (翻訳)
– Armin Ronacher 氏の問題提起
– 欲しいのは強力な型システムそのもの ≠型ヒント
●
代数的データ型 (Algebraic data type) の議論
– Python は言語の意味論が壊れてる?
●
Python 側実装と C 言語側実装による意味論の違い
●
CPython インタープリターの最適化のため
懸念 :Typed Clojure の現状
●
Why we’re no longer using Core.typed
●
CircleCI が本番環境で 2 年間使っていたが、止
めてしまった話
– 型チェックが遅くてインタラクティブに開発でき
ない
– core.typed が Clojure 言語全てをカバーしてない
– サードパーティライブラリの型アノテーションの
メンテが大変
展望
展望 : 構造的部分型 (Structual Subtyping)
●
構造的部分型の型チェックの前提案
– プロトコルという概念を導入
●
Sized, Iterable, Iterator など
– クラスの継承関係ではなく、メソッド実装の有無
で型チェックを行う (Go 言語のポリモルフィズム )
– うまくいけば 3.6 の PEP に出てくるかも?
●
クラスの継承関係で部分型を定義するのを公称
的部分型 (Nominal Subtyping) と言う
展望 : 構造的部分型への期待?
●
[Python-ideas] Structural type checking for
PEP 484
– Cory Benfield (hyper の作者 ) からの返信
– 自分は型ヒントに特に関心のない開発者の 1 人
だったんだけど、これは型チェックに関して懸念
していたことに対応できるものだと思う
まとめ
型ヒントの所感
●
型ヒントが成功を収めるかどうかは懐疑的
– 型ヒントが Python3 のキラーアプリというのは
まだ楽観的過ぎると私は思う→プロパガンダ
●
みんな強力な型システムを求めている
– NullPointerException の発生しない世界
●
型システムとプログラミングの関係を学ぶ
– プログラミングの幅が広がり楽しくなる!
Happy Coding
With Type Hints

Weitere ähnliche Inhalte

Was ist angesagt?

Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Preferred Networks
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
pospome
 

Was ist angesagt? (20)

3週連続DDDその2 深いモデルの探求(ドメイン駆動設計 第3部)
3週連続DDDその2  深いモデルの探求(ドメイン駆動設計 第3部)3週連続DDDその2  深いモデルの探求(ドメイン駆動設計 第3部)
3週連続DDDその2 深いモデルの探求(ドメイン駆動設計 第3部)
 
優れた研究論文の書き方―7つの提案
優れた研究論文の書き方―7つの提案優れた研究論文の書き方―7つの提案
優れた研究論文の書き方―7つの提案
 
ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計
 
デキるプログラマだけが知っているコードレビュー7つの秘訣
デキるプログラマだけが知っているコードレビュー7つの秘訣デキるプログラマだけが知っているコードレビュー7つの秘訣
デキるプログラマだけが知っているコードレビュー7つの秘訣
 
時系列解析の使い方 - TokyoWebMining #17
時系列解析の使い方 - TokyoWebMining #17時系列解析の使い方 - TokyoWebMining #17
時系列解析の使い方 - TokyoWebMining #17
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
 
全力解説!Transformer
全力解説!Transformer全力解説!Transformer
全力解説!Transformer
 
分散システムについて語らせてくれ
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
 
Attentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAttentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門まで
 
CV分野におけるサーベイ方法
CV分野におけるサーベイ方法CV分野におけるサーベイ方法
CV分野におけるサーベイ方法
 
Optimizer入門&最新動向
Optimizer入門&最新動向Optimizer入門&最新動向
Optimizer入門&最新動向
 
【DL輪読会】SimPer: Simple self-supervised learning of periodic targets( ICLR 2023 )
【DL輪読会】SimPer: Simple self-supervised learning of periodic targets( ICLR 2023 )【DL輪読会】SimPer: Simple self-supervised learning of periodic targets( ICLR 2023 )
【DL輪読会】SimPer: Simple self-supervised learning of periodic targets( ICLR 2023 )
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
 
Pycon reject banditアルゴリズムを用いた自動abテスト
Pycon reject banditアルゴリズムを用いた自動abテストPycon reject banditアルゴリズムを用いた自動abテスト
Pycon reject banditアルゴリズムを用いた自動abテスト
 
初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!
 
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
 
画像キャプションの自動生成
画像キャプションの自動生成画像キャプションの自動生成
画像キャプションの自動生成
 
モデル高速化百選
モデル高速化百選モデル高速化百選
モデル高速化百選
 
ゼロから始める自然言語処理 【FIT2016チュートリアル】
ゼロから始める自然言語処理 【FIT2016チュートリアル】ゼロから始める自然言語処理 【FIT2016チュートリアル】
ゼロから始める自然言語処理 【FIT2016チュートリアル】
 
GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出
 

Ähnlich wie Python と型ヒント (Type Hints)

Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
gintenlabo
 

Ähnlich wie Python と型ヒント (Type Hints) (20)

静的型付け言語Python
静的型付け言語Python静的型付け言語Python
静的型付け言語Python
 
Pythonと型チェッカー
Pythonと型チェッカーPythonと型チェッカー
Pythonと型チェッカー
 
mypy - 待望のPython3.9型ヒント対応
mypy - 待望のPython3.9型ヒント対応mypy - 待望のPython3.9型ヒント対応
mypy - 待望のPython3.9型ヒント対応
 
Pyconjp2014_implementations
Pyconjp2014_implementationsPyconjp2014_implementations
Pyconjp2014_implementations
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
PyPy 紹介
PyPy 紹介PyPy 紹介
PyPy 紹介
 
Python と型アノテーション
Python と型アノテーションPython と型アノテーション
Python と型アノテーション
 
C++勉強会in広島プレゼン資料
C++勉強会in広島プレゼン資料C++勉強会in広島プレゼン資料
C++勉強会in広島プレゼン資料
 
20170131 python3 6 PEP526
20170131 python3 6 PEP526 20170131 python3 6 PEP526
20170131 python3 6 PEP526
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)
 
明日からはじめるネットワーク運用自動化
明日からはじめるネットワーク運用自動化明日からはじめるネットワーク運用自動化
明日からはじめるネットワーク運用自動化
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第2回 ‟変数と型„
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
DS Exercise Course 2
DS Exercise Course 2DS Exercise Course 2
DS Exercise Course 2
 
TFLite_and_PyTorch_Mobile
TFLite_and_PyTorch_MobileTFLite_and_PyTorch_Mobile
TFLite_and_PyTorch_Mobile
 
Django_fukuoka
Django_fukuokaDjango_fukuoka
Django_fukuoka
 
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
 
Django_Fukuoka
Django_FukuokaDjango_Fukuoka
Django_Fukuoka
 
TypeScript で型を上手く使う試み.pdf
TypeScript で型を上手く使う試み.pdfTypeScript で型を上手く使う試み.pdf
TypeScript で型を上手く使う試み.pdf
 

Mehr von Tetsuya Morimoto

Python3 プログラミング勉強会
Python3 プログラミング勉強会Python3 プログラミング勉強会
Python3 プログラミング勉強会
Tetsuya Morimoto
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7
Tetsuya Morimoto
 

Mehr von 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 講座
 

Kürzlich hochgeladen

Kürzlich hochgeladen (11)

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 

Python と型ヒント (Type Hints)

  • 2. 自己紹介 ● 森本 哲也 – twitter: @t2y ● 白ヤギコーポレーション所属 – カメリオAPI開発 ( 興味がある方はブースへ ) ● エキスパート Python プログラミング共訳 ● プログラミング言語歴 – Python (3 年 ) – → Java (3 年 ) – → Go ( 半年 )
  • 4. Pythonのパラドックス ● 2004 年 8 月 Paul Graham – Python を学ぼうとするプログラマーは賢い ● Python 2.3.4 (2004-05-27): 2.3 の時代 – 新しい言語を学ぶ人たちはプログラミングが好き であり、仕事に役立つから学ぶわけではない – 曲解 : 「優秀な Java プログラマーを採用したかっ たら Python プログラマーを雇えば良い」 ● いまは成り立たない
  • 5. Python3 のパラドックス ● 2015 年 10 月 – Python3 を現場に導入しようとするプログラマーは 賢い – Python3 を導入する人たちはプログラミングが好き であり、現場で役立つから導入するわけではない – 曲解 : 「優秀な Python プログラマーを採用した かったら Python3 を現場に導入すれば良い」 ● それっぽい? ( 自己責任で! )
  • 6. 概要 ● 背景 – 漸進的型付け→関数アノテーション→ mypy ● PEP 484 〜型ヒント〜 – 目的 – 型ヒントのために定義された型 (Any, Union, etc) – ジェネリクス ● 懸念 – 型ヒントの批判、 Typed Clojure の現在 ● 展望 – 構造的部分型 (Structual Subtyping) へ Python3.5
  • 8. 背景 : 漸進的型付け (Gradual Typing) ● Jeremy Siek 氏と Walid Taha 氏が 2006 年に 考案した型システム – 静的型付けと動的型付けを組み合わせられる – 双方の型システムの良いとこ取りしたもの – Object 型ではなく Any 型を導入しなければならな い背景の説明 ● PEP 484 の理論的背景 ● 入門記事 : 漸進的型付けとは何か
  • 9. 背景 : 関数アノテーション (PEP3017) ● Python3.0 で導入 (PEP3017) – 2008-12-03 リリース – 関数に任意のアノテーションを書く仕組み ● PEP 484 を支える基本的な仕組み – 関数アノテーションの用途を型アノテーションに 限定した – 関数オブジェクトの __annotations__ 属性に保持 されるのは同じ
  • 10. 背景 :mypy プロジェクト (1) ● http://mypy-lang.org/ ● 作者 : Jukka Lehtosalo 氏 – プログラマーを 6 年、マネージャーを 2 年 – 2009 年からケンブリッジ大学の博士課程 ● 2012 PyCon Finland – MYPY: A PYTHON VARIANT WITH SEAMLESS DYNA MIC AND STATIC TYPING ● 静的型付けと動的型付けの融合 – PyPy や Cython がライバル、 GIL のない VM
  • 11. 背景 :mypy プロジェクト (2) ● 現時点の mypy ができること – GIL のない VM – 型アノテーション→ PEP 484 で標準化 – 静的型チェッカーとしての Lint ツール ● PEP 484 では型チェッカーは提供しない
  • 13. 型ヒント : サンプルコード # -*- coding: utf-8 -*- 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() -> None: raw_data = sys.argv[1] # type: str data = pretty_format(json.loads(raw_data)) print(data) data.append('mypy') main() $ mypy tutorial.py tutorial.py: note: In function "main": tutorial.py:14: error: "str" has no attribute "append"
  • 14. 型ヒント : 目的 ● 型アノテーションの構文を標準化 ● 静的解析 – Lint ツール ( オフライン型チェッカー ) ● IDE – コード補完やリファクタリング機能に利用 – Type Hinting in PyCharm ● ドキュメンテーション – 型アノテーションがそのまま使える? Python は 動的型付け言語
  • 16. 型ヒント :Any 型 ● 全ての型は Any 型のサブタイプ – object 型と似ているが、型チェッカーによる扱い が異なる ● object 型 – 型チェッカーは値のほとんどの操作を拒否する ● Any 型 – 型チェッカーは値の全ての操作を許容する
  • 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回「代数データ型」でいろいろなデータを表してみる
  • 19. 型ヒント :Optional 型 ● 直和型の応用 ● Union[T1, None] と Optional[T1] は等価 – None を取り得ることが明示される – None は多くの操作が型エラー ● Java の NullPointerException はこりごり – @Nonnull, @Nullable のアノテーションを明示 – Collections.emptyList(), Collections.emptyMap() ● Null 安全を型システムで保証する世界へ
  • 20. 型ヒント :Optional 型の例 from typing import Optional, Union def func1(data: Optional[int]) -> int: return 3 + data def func2(data: Union[int, None]) -> int: return 3 + data def func3(data: int=None) -> int: return 3 + data これらは等価な型ヒント ・デフォルト引数に None を指定したときも Optional 型として扱う TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
  • 21. 型ヒント : ジェネリクス ● コンテナー内の要素に期待する型を示す ● TypeVar というファクトリーを使って型変数を 定義する from typing import Sequence, TypeVar T = TypeVar('T') # Declare type variable def first(l: Sequence[T]) -> T: # Generic function return l[0]
  • 22. 型ヒント :TypeVar ● TypeVar のコンストラクタに渡す型変数を表す 文字列と代入する変数名は同じでなければいけ ない from typing import TypeVar X = TypeVar('X') # correct Z = TypeVar('Y') # error mypy generics_typevar.py:4: error: Unexpected TypeVar() argument value
  • 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"
  • 28. 型ヒント : スタブファイル ● 型チェッカーのための拡張モジュール ● 型ヒントを Python モジュールではなく外部の ファイルに書き出すためのもの ● 拡張子は .pyi ● 主には ( 型ヒントがない ) サードパーティのラ イブラリと一緒に型ヒントを使うため – スタブを集める typeshedリポジトリもある ● TypeScript でいうところの DefinitelyTyped
  • 29. 型ヒント : スタブの例 class tzinfo: def tzname(self, dt: Optional[datetime]) -> str: ... def utcoffset(self, dt: Optional[datetime]) -> int: ... def dst(self, dt: Optional[datetime]) -> int: ... def fromutc(self, dt: datetime) -> datetime: .. class timezone(tzinfo): utc = ... # type: tzinfo min = ... # type: tzinfo max = ... # type: tzinfo def __init__(self, offset: timedelta, name: str = '') -> None: ... def __hash__(self) -> int: ... datetime.pyi
  • 32. 懸念 :(Python に ) 必要か? ● Python に型ヒントは本当に必要なのか? ● Revenge of the Types: 型の復讐 (翻訳) – Armin Ronacher 氏の問題提起 – 欲しいのは強力な型システムそのもの ≠型ヒント ● 代数的データ型 (Algebraic data type) の議論 – Python は言語の意味論が壊れてる? ● Python 側実装と C 言語側実装による意味論の違い ● CPython インタープリターの最適化のため
  • 33. 懸念 :Typed Clojure の現状 ● Why we’re no longer using Core.typed ● CircleCI が本番環境で 2 年間使っていたが、止 めてしまった話 – 型チェックが遅くてインタラクティブに開発でき ない – core.typed が Clojure 言語全てをカバーしてない – サードパーティライブラリの型アノテーションの メンテが大変
  • 35. 展望 : 構造的部分型 (Structual Subtyping) ● 構造的部分型の型チェックの前提案 – プロトコルという概念を導入 ● Sized, Iterable, Iterator など – クラスの継承関係ではなく、メソッド実装の有無 で型チェックを行う (Go 言語のポリモルフィズム ) – うまくいけば 3.6 の PEP に出てくるかも? ● クラスの継承関係で部分型を定義するのを公称 的部分型 (Nominal Subtyping) と言う
  • 36. 展望 : 構造的部分型への期待? ● [Python-ideas] Structural type checking for PEP 484 – Cory Benfield (hyper の作者 ) からの返信 – 自分は型ヒントに特に関心のない開発者の 1 人 だったんだけど、これは型チェックに関して懸念 していたことに対応できるものだと思う
  • 38. 型ヒントの所感 ● 型ヒントが成功を収めるかどうかは懐疑的 – 型ヒントが Python3 のキラーアプリというのは まだ楽観的過ぎると私は思う→プロパガンダ ● みんな強力な型システムを求めている – NullPointerException の発生しない世界 ● 型システムとプログラミングの関係を学ぶ – プログラミングの幅が広がり楽しくなる!