第4回Python文法詳解を詳解する会に参加した。講師である石本さん、会場である(株)クロス・マーケティング様には感謝を申し上げたい。初台は大学時代通過するだけの駅で初めて降りた。なんだかお洒落なビルであった。 折角なので、記録したメモを公開したい。 なお、私は当日伊豆大島土産の青いTシャツを着て会議室の中央に座っていた。このご時勢にノートパソコンではなく紙のノートに万年筆というスタイルであった。
Python文法詳解を詳解する会 #4
5章:ステートメント
if
文
- 条件式はブール式以外でもOK。
- 何もしないが文法的に空白が許されない場合は
pass
を使う。
while
文
else
節がある。break
文が実行されなかった場合にelse
ブロックを実行する。
for
文
- 変数にイテラブルオブジェクト(P.24, P.258)から取り出した要素を先頭から代入し
for
ブロック内の処理を実行 - 変数への代入にはアンパック、
*args
が使える。
L = [(1, 2), (3, 4, 5), (6, 7, 8, 9)] for car, *cdr in L: print(car, cdr)
1 [2] 3 [4, 5] 6 [7, 8, 9]
for
文にもelse
節がある。for
ループがbreak
で中断されずに終了した場合のみelse
節が実行される。
range 函数
range
オブジェクトはイテレータではない。
ls = range(3) for x in ls: print(x) for y in ls: print(y)
0 1 2 0 1 2
(記録者注)イテレータの場合の動作。iter
函数でイテレータを返す。
it = iter(range(3)) for x in ls: print(x) for y in ls: print(y)
0 1 2
enumrate 函数
L = ['one', 'two', 'three'] for num, value in enumerate(L, 1): print(num, value)
1 one 2 two 3 three
例外処理
- Pythonは例外をよく使う。
try
,except
,else
,finally
からなる。else
ブロックはtry
ブロックで例外は発生しなかったときに実行される。except
節で指定した以外の例外が発生した場合に実行されるわけではない。except...as
で指定した変数はハンドラを抜けると削除される(Py3)。メモリリーク対策のため。finally
ブロックはexcept
やelse
ブロックのあとに実行される。- CPythonでは
finally
ブロックではcontinue
文を実行できない。言語仕様では定義されていない。 finally
ブロックでreturn
文を実行すると例外を握りつぶす。BaseException
から直接派生している例外をアプリケーション側では無視してはいけない。Exception
またはその派生の例外をexcept
で指定する。
raise
文
raise
文には送出する例外オブジェクト、または例外オブジェクトの型を指定する。- 例外オブジェクトを指定せずに
raise
文を実行すると処理中の例外オブジェクトがそのまま再送出される。 - 例外処理中に例外が発生した場合、例外を連結して両方送出する。これはPy3で導入された。 Py2では上書きされていた。
トレースバックオブジェクト
with_traceback()
メソッドで元の例外オブジェクトのトレースバックを新しい例外オブジェクトに設定できる。 あまり使う機会がない。
assert
文
- Python起動時に最適化オプション(
-O
または-OO
)を指定すると実行されない。
with
文
- オブジェクトによって動作が異なる。
with
文に対応したオブジェクトをコンテキストマネージャと呼ぶ。- カンマで複数のコンテキストマネージャを指定することが出来る。
6章:関数
関数定義
- 函数内で定義した変数及びインポートしたモジュールは函数内のみ有効
return
文が実行されないまたは省略した場合、函数はNone
を返す。 (記録者注: Rubyだと最後に評価した式の値を返す、だった気がした。)- 函数定義は
if
ブロック内に記述することも出来る。条件によって中身が異なる函数が定義できる。 - 可変長引数
*args
def spam(ham, egg, *args): print('ham={}, egg={}, args={}'.format(ham, egg, args)) spam(1, 2, 3, 4, 5)
ham=1, egg=2, args=(3, 4, 5)
- キーワード専用引数。
*args
のような*
つきの引数の後に指定した引数は位置で指定することが出来ない。 キーワードで指定する必要がある。 引数リストに
*
だけ指定すると、*
よりも右側で指定した引数は必ずキーワード引数として指定しなければならない。デフォルト引数に更新可能オブジェクトを入れる場合には注意が必要。
def spam(ham=[]): ham.append(1) print(ham) spam() spam() spam()
[1] [1, 1] [1, 1, 1]
- デフォルト引数が作成されるのは函数オブジェクトを作成するタイミング。
for i in range(10): def spam(ham=[]): ham.append(1) print(ham) spam()
- 函数アノテーション。型チェック機能がPy3.5から導入されるかもしれない。
lambda
式。式で函数オブジェクトを生成する。ブロックを含めることが出来ない。 Py3で削除されるかと思われたが生き残っている。
モジュールとパッケージ
- エンコーディングはUTF-8がデフォルト。
- モジュールのトップレベルで定義した変数はグローバルスコープに入る。
- 函数内で
global
文を使うことでローカル変数ではなくグローバル変数として扱うことが出来る。 - グローバル変数は事前に定義する必要は無い。
from ... import ...
でモジュールを指定する場合、__all__
にシーケンスが定義してあれば__all__
に含まれる名前のオブジェクトのみ、__all__
が無い場合は名前の一文字目が_
ではないオブジェクトがすべてインポートされる。- モジュールの検索パスは
sys.path
に指定されたものを検索する。 - ユーザのホームディレクトリにOS毎に特定のディレクトリを作成しておくと自動的に
sys.path
に追加される。 - zipファイルからもインポートできる。
- パス設定ファイルも利用できる。
virtualenv
などで利用されている。
パッケージ
- ディレクトリに
__init__.py
がある場合、パッケージとしてインポートできる。 - 同じパッケージ内にあるモジュールは相対インポートを指定できる。
Py3.3から名前空間パッケージが導入され、
__init__.py
が存在しなくてもsys.path
に登録されたディレクトリのサブディレクトリも名前空間パッケージとしてインポートできる。 (記録者注: Zopeにも同様の機能があるらしい。)モジュールの実行には以下3つの方法もある。
-m
オプションでモジュール名を指定して実行__main__.py
を含むディレクトリを指定して実行- zipファイルを指定して実行
__main__
モジュール
- 実行中のスクリプトの名前は
__name__
に入っている。
if __name__ == '__main__': spam()
コンパイル済みモジュールファイル
- モジュールをインポートするとバイトコードにコンパイルしてから実行する。
- コンパイル済みモジュールは
__pycache__
サブディレクトリに作成される。 - Py3.5で削除されるかもしれない。議論されている。 (了)
感想
初めて社外の勉強会に参加したがとても面白かった。普段Pythonの話なんてほとんどできないのでその反動もあるが本当に楽しかった。 ちょうどEffective Pythonの自家邦訳を進めている最中で函数のところはよく文法詳解を参照していたのだがそ、そうだったのか!ということもあった。 終了後のパブにもお邪魔させていただいた。興味深い話が多くこれまた楽しかった。見知らぬ人たちとお酒を飲みのも初めてであった。 懐が寂しくちゃんとつまみを提供できなかったのが悔やまれる。