先日からちょこちょこ読んでいるオライリーPython豆知識収集の続き。

  • lambda式の書き方はこう。PHPとかJSの無名関数にあたるものだが、lambdaの文字があるだけでみょ~に難解に見えるんだよなあ…。
lambda x , y: x + y
  • lambda式はコード凝縮のためのものである。def文でも同じことが必ずできる。ああよかったですハイ。
  • print()関数と同じことが、 sys.stdout.write(str(x) + "\n") で出来る。
  • 前回も書いたがif文凝縮の方法。
# 通常のifステートメント
if a:
    b
else:
    c
# 他のパターン
b if a else c
# また他のパターン
((a and b) or c)
  • range()関数はリストを生成する。for文で散々使っていたrange()だったが、まったく知らなかった。そもそも関数だという認識も希薄だったな…。
  • リスト内包表記をすると入れ子構造を凝縮できる!
lis = [x + y for x in  [0,1,2] for y in [100,200,300]]
# lisは[100, 200, 300, 101, 201, 301, 102, 202, 302]となる
  • と興奮したが俺の趣味の範囲ではいまのところ、for文でlist.append()を使うことが多いのでこれは大して使えんか。
  • リスト内包表記でマトリクスから要素を取り出す
lis0 = [[1,2], [3,4], [5,6]]
lis1 = [row[1] for row in lis0]
# lis1は[2, 4, 6]
  • これはちょっと便利かも。データベースいじりではカラム単位で要素を抜き出したいことがままあるが、それと同じことができるというわけか。
  • yieldは関数をジェネレータにする文であり、ジェネレータが値を生み出す文である。
  • ジェネレータ式は次のようなものである。
g = (x**2 for x in range(4))    # 丸カッコを使う
g.next()                        # 0
g.next()                        # 1
  • 関数づくりのコツは、役割を一つに絞ること、規模を小さく、一画面に収まる程度にすること。
  • 関数は変数にフツーに代入できる。
def echo(a):
    print(a)
x = echo
x("Midori")
  • となると、スクリプト内で組み込み関数の名に何かを代入すると、その組み込み関数を使えなくできるってことか。
  • モジュールの中で中心をなすファイルをトップレベルファイルという。
  • import文を使った際の module.method() みたいな書き方を完全名という。
  • from文はモジュール内の特定の変数のみコピーするものである。 from module import method。なお from module import * は全変数名のコピーである。fromを使えば完全名を使う必要がなくなるが、俺は完全名が好みかな。並びに、asでモジュール名を短くするのも好み。
  • import文を二度実行して変数名をリセットすることは不可。変数のリセットがしたいときは importlib.reload() を使う。
  • モジュールの名前空間の実体はディクショナリオブジェクト。 __dict__.keys() で変数の一覧を見ることができる。以前変数の自動生成を試みたときディクショナリを変数として利用する方法を思いついてクリアーしたことがあったが、あのときのひらめきは正しかったのだな。
  • ところで名前空間という用語が俺はずっと理解できなかったのだが、ここまで読み進めればさすがにわかってくる。すなわち名前空間ってのは、変数群のスコープの範囲を表すのだろう。
  • パッケージインポートとは、ディレクトリパスを指定してimportすることである。パッケージインポートで経由するディレクトリには __init__.py が必要。このファイルは空白であってもよい。
import dir1.dir2.module
  • __init__.py 内で __all__ という属性内に変数のリストを作ると、 import * によってインポートが行われた際にインポートするモジュールを選択できる。
  • パッケージとは、pyコードを収めたディレクトリのことである。
  • from __future__ import {機能名} とは、将来デフォルトになる予定の機能をオンにする文である。
  • ビルトイン属性 __name__ はモジュールを作ると自動的に与えられる。そのモジュールがトップレベルファイルとして扱われているときは "__main__" が値として格納される。サンプルコードで if __name__ == "__main__": foo() という文は腐るほど見てきて、いつも意味がわからなかったがこういうことだったのか。そのファイルがメインで使われているときはfoo()を実行し、ただimportされたモジュールとして扱われているときは何もしないという意味だったか。
  • 相対インポートとは、そのステートメントが属するパッケージを優先的に検索する方法である。 from . import x という風に書く。なお from .. import x と書くとひとつ上階層のディレクトリから検索できる。

豆知識収集のスタンスではあったけれども、かなり実際書くときに役立つ部分だったなあ。