もっと知りたいPython3000
第3回 言語仕様,組み込み関数,クラスへの変更
Pythonでは,ソースコードの1行目,または2行目に #coding: utf-8のように記述することによって,ソースコードのエンコードを指定できます。Python 2.5からは,マルチバイト文字列を含むソースコードのエンコードを必ず明示するよう仕様が変更されています。エンコードを指定することで,インタプリタはソースコードをUnicodeとして扱うことができます。
マルチバイトについては,Python 2.xでは,文字列リテラルやコメント内に利用できるだけでした。Python 3.0からは,変数名などの識別子にUnicodeを利用できるようになりました。英数字を含むASCII文字列だけでなく,アクサンやウムラウトを含む文字,ロシア語など,より多彩な文字列を変数名やクラス名に利用できるようになっています。
このように,Python 3.0では言語仕様に近い部分にも多くの変更点があります。今回は,言語仕様やクラス,グローバル関数,標準モジュールに加えられる変更点について概観したいと思います。
nonlocal文
Pythonはとてもシンプルなスコープ(名前空間)の規則を持っています。ユーザが通常扱う範囲の名前空間は「モジュール(グローバル)スコープ」「ローカルスコープ」「ネストされたスコープ」の3つです。変数や名前を持つ関数などのオブジェクトがどのスコープに属するかは,オブジェクトが最初に定義された位置に依存します。
トップレベルで定義された変数はモジュールスコープに属します。関数内で定義された変数はローカルスコープに属します。Pythonでは,変数を定義するには代入を行います。このため,関数内のローカルスコープでモジュールスコープにある変数を更新しようとして代入すると,ローカルスコープに同名の新しい変数が作られてしまいます。このようなことを避けるため,Pythonではglobal文を使い,モジュールスコープにある変数などのオブジェクトを参照することができました。
Pytohn 3.0では,global文に似たnonlocal文が追加されます。nonlocal文を使うと,入れ子に定義された関数から,すぐ外側の(ローカル)スコープにあるオブジェクトを参照することができます。
例外に関する変更
Pythonの「例外」は、仕様の中でもあいまいさや機能の重複があると議論の的になってきた仕様のひとつです。Python 2.xで例外を受け取るには,リスト1のようにします。
リスト1 Python 2.xでの例外の受け取り
try:
# some code
except OSError, e:
# do something using e
Pythonはすべてがオブジェクトなので,例外もオブジェクトです。カンマの後にあるeというオブジェクトには,例外オブジェクトが代入されます。カンマの前に「OSError」とあるので,ここではOSErrorに含まれる例外のみを受け取ります。
では,1つのexcept文で複数の例外を受け取りたいときはどうすればいいでしょうか。カンマは例外の種類と例外を受け取るオブジェクトの区切りに使われてしまっているので使えません。例外を列記するにはリスト2のようにします。
リスト2 Python 2.xでの複数の例外の受け取り
:
except (OSError, IOError), e:
# do something using e
例外を投げるための記法のあいまいさも,やり玉にあがることが多い仕様といえます。リスト3に示す2つは,例外とオプションを指定するための記法で,どちらも同じ内容を示します。
リスト3 Python 2.xでの例外指定
raise OSError, 'foobarbaz'
raise OSError('foobarbaz')
例外に関する非直感的な仕様とあいまいさを解決するため,Python 3.0では例外の文法にメスが入ります。
まず,例外を受け取る場合。2.6,および3.0では新しいキーワード as を使ってリスト4のように書きます。
リスト4 Python 3.0での例外指定
except OSError as e:
複数の例外を1つのexcept文で受けたいときには,
except (OSError, IOError) as e
のように例外をかっこで囲んで列挙します。
print()関数,exec()関数
Pythonは「式」と「文」の間に明確に区切りを設けています。「式」とは関数呼び出し,比較などを行う構文です。リスト内包表記やジェネレータ式も式の仲間です。1つの行には複数の式を書くことができます。
「文」とはforやif,関数定義を行うdefなどを指します。プログラムの流れを変えたり,新しいオブジェクトを生成するための命令です。文には改行が必要です。Pythonでは代入(変数定義)も文です。文は1行に1つしか書けませんので,C言語のようにif文やfor文の中で変数定義をすることができません。
Python 2.xまでは,printやexecが文として定義されていました。特定の処理を行うための命令が,ifやforと同じ文として定義されていることは言語としての一貫性を崩すということで,かつてより議論の対象となることがありました。
Python 3.0では,printとexecが組み込み関数として再定義されます。関数ですので,print('foo') のように後ろにかっこをつけて呼び出す必要があります。
printが文であったときに特に評判が悪かったのが,出力先の指定方法です。printは特に指定をしないと標準出力に結果を出力します。出力先を変えたいときには,リスト5のようにする必要がありました。
リスト5 Python 2.xでprintの出力先指定を変える
print >>>sys.stderr, "Some error occured!"
3.0のprint()関数では,引数として出力先を与えます。
リスト6 Python 3.0のprint()の出力先指定
print("Some error occured!", file=sys.stderror)
その他,末尾に追加する改行の変わりに使う文字列を指定する「end」,カンマで区切って渡す引数のセパレータを指定する「sep」など,ほかにも引数が使えるようになっています。
もっと知りたいPython3000
- 第4回 Python 2.xから3.0への移行方法
- 第3回 言語仕様,組み込み関数,クラスへの変更
- 第2回 組み込み型への変更
- 第1回 Python 3.0の思想と意義


