特集
» 2017年02月24日 05時00分 UPDATE

特集:Python 3.6の新機能:フォーマット文字列リテラル/非同期プログラミング機能など、Python 3.6で追加された新機能をザックリ理解しよう (1/2)

2016年12月にPythonの最新版であるバージョン3.6がリリースされた。本稿ではその中でも特徴的な新機能を幾つか紹介していく。

[かわさきしんじ,Insider.NET編集部]
「特集:Python 3.6の新機能」のインデックス

連載目次

 2016年12月23日にPythonの最新版であるバージョン3.6がリリースされた。本稿ではその中でも特徴的な新機能を幾つか紹介していく。

Python 3.6で追加された主要な新機能

 Pythonのドキュメント「What's New In Python 3.6」や、そのリリースノート(英語)にはPython 3.6で追加された機能や、変更点がまとめられている。

 大まかなところを拾っていくと、構文的には以下のような機能が追加されている。

  • フォーマット文字列リテラル: いわゆる文字列補間
  • 数値リテラルでのアンダースコアの使用: 「123456」を「123_567」などと記述可能
  • 型注釈: 関数のパラメーター/戻り値の型に加えて、変数にも型注釈を付加可能に
  • 非同期ジェネレータ: Python 3.5の非同期イテレータに加えて、非同期ジェネレータもサポートされた
  • 非同期内包表記: 「async for」「await」などを内包表記中に記述可能に

 本稿ではサンプルコードとともに、上記について見ていくことにしよう。これ以外の変更点や改善点については前述のリンクなどを参照されたい。

フォーマット文字列リテラル

 フォーマット文字列リテラルとは、他の言語においても最近になって実装されることが多くなったいわゆる「文字列補間」のPythonバージョンのことだ(PEP 498。「PEP」は「Python Enhancement Proposal」の略で「Pythonの機能追加や改善策に関する提案」のこと)。Pythonでは「f-string」「f文字列」などと呼ばれることもある。

 「f文字列」という名前から想像できるかもしれないが、フォーマット文字列リテラルは文字列を囲むクオーテーションの前に「f」を前置し、その内部では「{式}」と記述することで、その部分にその式の値(例えば、変数の値)を埋め込める。

 以下に例を示す。

name = 'insider.net'
print(f'name: {name}')       # 出力結果: name: insider.net
print(f'2 ** 4 = {2 ** 4}'# 出力結果: 2 ** 4 = 16


フォーマット文字列リテラル

 「出力結果」をコメントとして含めてあるが、これを見ると「{}」内に記述した変数の値や計算結果が補間されているのが分かる。特に説明はいらないだろう。なお、「{}」内には以前よりPythonで使われてきた書式指定文字列も記述可能だ(「:」以降に記述)。以下に例を示す。

print(f'2 ** 12 = {2 ** 12:>+8,d}'# 出力結果: 2 ** 12 =   +4,096
print(f'2 ** 12 = {2 ** 12:#_b}')    # 出力結果: 2 ** 12 = 0b1_0000_0000_0000


書式指定文字列の利用例

 最初の例は「2 ** 12」の評価結果を「右寄せ(>)、正負両方の値で符号を付加(+)、8桁幅(8)、3桁ごとにカンマ(,)を挿入(,)、10進数(d)」で表記することを指定するものだ。次の例では同じく「2 ** 12」の評価結果を「0bを前置(#)、4桁ごとにアンダースコア(_)を挿入、2進数(b)」で表記するように指定している(「#」指定については、補間する値の型によって意味が異なってくるので注意)。なお、アンダースコアを挿入できるのは、Python 3.6の新機能の1つでもある。

 書式指定文字列の構文の詳細についてはPythonのドキュメント「書式指定文字列の文法」「書式指定ミニ言語仕様」などを参照してほしい。

数値リテラルでのアンダースコアの利用

 数値リテラル内にアンダースコア(_)を記述できるようになった(PEP 515)。これは、桁数の多い数値リテラルの可読性を高めるためのものだ。アンダースコアは基数の指定子(「0b」「0o」「0x」)の直後、数字と数字の間に挿入できる。ただし、リテラルの先頭と末尾に置くことはできず、連続したアンダースコアは認められない。以下に例を示す。

num = 0x_FFFF_FFFF
print(f'0xffffffff = {num:,}')       # 出力結果: 0xffffffff = 4,294,967,295
num = 4_294_967_296
print(f'4_294_967_296 = {num:#_x}'# 出力結果: 4_294_967_296 = 0x1_0000_0000
#num = 1000_   # エラー(末尾のアンダースコア)
#num = _1000   # エラー(先頭のアンダースコア)
#num = 1__000  # エラー(連続したアンダースコア)


数値リテラルでのアンダースコアの利用

 なお、前節でも見た書式指定文字列内でのアンダースコアの利用は、数値リテラル内でのアンダースコアの利用を提案したPEP 515で規定されている。これを指定した場合、10進表記の場合は3桁ごとに、2進/8進/16進表記の場合は4桁ごとにアンダースコアが挿入されるようになっている。

型注釈/型ヒント機能の拡張

 型注釈あるいは型ヒントと呼ばれる機能はPython 3.5で、関数の引数と戻り値型について導入されたものだが(PEP 484)、Python 3.6ではこれが拡張されて、変数(クラス変数、インスタンス変数を含む)についても型注釈を付加できるようになった(PEP 526)。

 型注釈の詳細については割愛するが、基本的なことをいえば変数やパラメーターの名前に続けて「: 型名」と記述する。関数の戻り値については「-> 型名」で指定する。以下に例を示す。

def foo(num: int) -> str:
  return str(num)

print(foo('string'))  # エラー
print(foo(100))       # OK

num = '100'
print(foo(num))       # エラー


型注釈/型ヒントの利用例(thint.pyファイル)

 型注釈/型ヒントはあくまでも静的な型解析を行うためのものであり、pythonコマンドで上記のスクリプトを実行する際には無視される。型解析を行うにはmypyなどのツールを使用する必要がある。上のコードには型に関するエラーが含まれてはいるが、実行は可能だ。以下に実行結果を示す。なお、このコードでは関数のパラメーターと戻り値型にのみ型注釈を付加しているので、Python 3.5/3.6のいずれでも実行可能だ。

> python thint.py
string
100
100


型注釈を含むPythonコードの実行

 先ほども述べたように、型チェックを行うにはmypyなどのツールが必要だ。mypyをインストールするにはpipコマンドを使用する。

> pip install -U mypy-lang
> pip install -U "typed_ast >= 0.6.3, < 0.7.0"


mypyとPython 3.6構文を解釈させるために必要なtyped_astパッケージのインストール

 本稿執筆時点(2017年2月23日)では、typed_astパッケージの最新版をインストールすると、Python 3.6の構文をうまく解析できなかったので上記のコマンドラインではバージョンを指定してインストールしているが、これは将来的に解消されるはずだ(あるいは「pip install -U mypy-lang」コマンドでうまく依存関係を調整できるかもしれない)。

 mypyをインストールしたら、コマンドラインで静的型チェックを行えるようになる。以下に例を示す。

> mypy thint.py
thint.py:4: error: Argument 1 to "foo" has incompatible type "str"; expected
"int"
thint.py:8: error: Argument 1 to "foo" has incompatible type "str"; expected
"int"


4行目と8行目の整数値が期待されるところで、文字列が渡されているためにエラーが発生

 エラーが発生したのは、先のコードで「# エラー」とコメントを入れた行と同じであり、静的型解析が機能していることが分かるはずだ。

 ここまでは、Python 3.5で追加された関数のパラメーター/戻り値型について型注釈を含めていたが、ここで先ほどのコードを次のように変更してみよう。

def foo(num: int) -> str:
  return str(num)

print(foo('string'))
print(foo(100))

num: int = '100'
print(foo(num))


変数にも型注釈を追加

 Python 3.6では「型注釈を変数に対しても付加できる」ようになったので、ここでは「変数numはint型」と注釈を付けている。これをPython 3.5のmypyで静的に型解析すると、次のような結果になる(Pythonの環境構築の都合により、macOS上で実行)。

$ python --version
Python 3.5.3

$ mypy thint.py 
thint.py:7: error: Parse error before :

$ python thint.py 
  File "thint.py", line 7
    num: int = '100'
       ^
SyntaxError: invalid syntax


Python 3.5では変数に対する型注釈は行えない

 ご覧の通り、mypyは7行目でパースエラーを発生している。その下のpythonコマンドでも構文エラーが発生した。これに対して、Python 3.6で静的型チェックを行った様子が以下だ。

> python --version
Python 3.6.0 :: Anaconda 4.3.0 (64-bit)

> mypy --fast-parser --python-version 3.6 thint.py
thint.py:4: error: Argument 1 to "foo" has incompatible type "str"; expected
"int"
thint.py:7: error: Incompatible types in assignment (expression has type "str",
variable has type "int")

> python thint.py
string
100
100


Python 3.6では変数に対する型注釈が可能

 中央の出力に注目してほしい。まず、本稿執筆時点ではPython 3.6の構文をmypyに解釈してもらうには「--fast-parser」オプションと「--python-version 3.6」オプションの指定が必要になる。また、前者のオプションを指定するには「typed_ast」パッケージの適切なバージョンも必要になる(そのため、上のpipコマンドではバージョンを指定して、typed_astパッケージをインストールしている)。

 出力結果を見ると、7行目で「int型の変数に文字列値を代入しようとした」ためにエラーが発生していることが分かる。Python 3.5のmypyでは「: num」の部分がパースエラーとなっていたが、Python 3.6ではきちんとこれが解釈されているということだ。

 さらに最後のpythonコマンドではエラーを発生することなく、スクリプトが実行できていることも分かる。

 非常に簡単な例だが、Python 3.5では関数のパラメーター/戻り値型に対する型注釈/型ヒント機能が実現され、Python 3.6ではそれがさらに変数でも使用できるようになったことが分かったはずだ。Pythonのtypingモジュールを使用すると、さらに高度な型指定や型操作も可能だが、これについては機会があれば別途ご紹介したい。

 なお、mypyによる型チェックが可能な環境では、Visual Studio CodeにPython拡張機能をインストールし、設定を記述することで、次のようにPythonコード記述時に静的型チェックを行うことも可能だ。

Visual Studio CodeでPythonコードの静的型チェック Visual Studio CodeでPythonコードの静的型チェック

 最後に、非同期処理についても簡単に見ておこう。

       1|2 次のページへ

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。