のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

PyConJPで触発されてPythonのType Hints(型ヒント)について書いてみた

Sponsored Links

皆さんこんにちは
お元気ですか。ラーメン食べたくなってきた。

私自身は自他共に認めそうなPython2.7.x userのつもりなのですが、
PyConJP2016でAndrey Vlasovskikh氏の講演でType Hints(型ヒント)の話があって
Python3.5すごいとか思いながら聞いてました。

ぶっちゃけ型ヒント何か知りません。

ということで、今回はPythonにおけるType Hintsを調べてみました。

Type Hintsについて

そもそもType Hintsってなに?

型に対するアノテーションです。具体的には実例を見るとおそらくわかりやすいです。

PEP484に規定されたType Hintsを提供するらしく、Python3.5で導入されています。
何のことやらわからないので、早速読んでみようと思ったら意外に長かったので読めておりません。
www.python.org

何が嬉しいのか

調べるとどうやらこんなメリットがあるそうです。

  1. Type Hintsを使うことで静的解析を容易にする。
  2. 容易なリファクタリングドキュメンテーションの作成
  3. アノテーションの標準的な書き方の定義

調べていたのですが、このあたりであまり見慣れない名前なので、何を言っているんだろうとおもってきてました・・・
ということで、そろそろ実例を

実例

よくあるチュートリアルの例

さて、既に調べるのに疲れたのでPython3.5に書いてある例に触ってみましょう。

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

name:strが、name変数がstr型であること、 -> strが返り値がstrを期待するといったことを示しています。

変数の別名

変数は前の紹介のstrだけではなく、複数の型を定義することができます。
次にその例を掲載します。
因みに、Tuple等を使って、定義することができます。

from typing import TypeVar, Tuple

T = TypeVar('T', int, float, complex)
def typetest(var: Tuple[T, T]) -> Tuple[T, T]:
    return var

Collections

Collectionsを使う場合はtypingのListやSetを使うことができます。
以下には例を記載します。

# coding:utf-8
from typing import TypeVar, List

T = TypeVar('T', int, float, complex)

def collection_test(list_var: List[T]) -> T:
    return list_var[0]

Generics

Genericsを使うと、ユーザ定義のGenericsを書くことができます。
ここまで来るとC++のtemplate構文を思い出してきますが、
そんなものを書くこともできます。

# coding:utf-8
from typing import TypeVar, Generic

T = TypeVar('T', int, float, complex)

class GenericTest(Generic[T]):
    def __init__(self,init: T):
        self.init = init

    def get_init(self) -> T:
        return self.init

    def set_init(self, init: T):
        self.init = init

書いてみたけど、どんな効果があるのでしょう

ここまでいくつか試しに書いてみましたが、
実際にどんな効果があるのかを確認したいので、見てみましょう。

PyCharm

PyCharmのVersion5.0以降でType Hintsがあることによって、
警告を出すようになります。

f:id:tereka:20160924004700p:plain

書いている時に、実際に自分が期待していない型を入力していることがわかるので、
その地点で警告を出してくれます。超便利
C++とか書いている人だと、結構ありがたいような感じではないでしょうか。

Mypy

Mypyは経験的な静的チェックのツールで、動的、静的のタイピングの良いところ取りする為に開発したようです。
Pythonの強力かつ、便利な型チェックで、基本的なPythonプログラムをサポートしているそうです。

Mypyが先に作成されて、Type Hintsとして導入されたようです。
インストールは次のコマンドです。私は知りませんが、mypyと呼ばれるpipで取得できるソフトウェアは別の内容とのことです。

pip install mypy-lang

さて、試しに次のコードに対してmypyを書けてみようと思います。
型が合わない、greetingに42のintを使っています。

# coding:utf-8

def greeting(name:str) -> str:
    return 'Hello, {}'.format(name)

greeting(42)

次のコメントが出てきます。

mypy TypeHints/typehint.py
TypeHints/typehint.py:6: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"

つまり、greeting関数に対して、第一引数はstrを期待しているが、
intを与えていると言われています。
ここで期待していない値を投入していることがわかります。

最後に

Type Hintsは面白いけれどもversion2,3適用が難しそうだから少なくとも後数年は使わないかな
どうやらAndrey Vlasovskikh氏曰く、Python2のほうがPyCharm的には利用者が多いそうなので、
Python3がそれをうわまわる人数になったときにどうなるかによってType Hintsの扱いをどうするかとか、
コーディング規約が変わっていくのかなと思ったりもします。

参考にType Hintsに触れている規約があったら見てみたいとも思っています。