diveintopython 4章読書メモ

最近になって読書を再開.
やっぱり考えたことなんかをアウトプットしないと効率よくないなあと感じつつ,読書した時のメモとして.
本家なんかに書いてあるコードは書かずに,試したものとかを書いておく.本家コードはリンクとして残す.
ぶっちゃけただのメモなので,人のためにはならんはず.

4章始まる

Chapter 4. イントロスペクションの力

  • 関数の使い方から組み込み関数の紹介
  • マップしながらフィルタリングするリスト
  • 三項演算子を作るトリック
  • ラムダ関数のトリック

が出てくる.
このトリックがおもしろい.この章からすげーなーと思える要素がたくさん.(それだけ知らないことだらけ)
(文字列整形はCでやったにしろ,すっかり忘れててスゲーさせていただきました.いやリストのマッピングもよくわからなかったのでそれも新鮮)

関数の使い方

引数の定義にはオプションが使える(デフォルト値

def info(object, spacing=10, collapse=1):

引数を使うときは,オプションで使った名前を指定できる(名前付き引数

info(odbchelper, collapse=0)
info(spacing=15, object=odbchelper)

名前の師弟をすると引数の並びは関係ないらしい.
そういう意味なのか,引数は単純に辞書らしい.
あーそうか,だったらキーを対応させた辞書を投げたら動くのかなと思ってやってみたけど辞書は一つの引数として対応された.

def testprint1(num=00,title="nontitle",text="haloo python world"):
  print("[%d] %s : %s" % (num,title,text))

In [14]: testprint1()
[0] nontitle : haloo python world

In [15]: testprint1(1,"title1","HELLO PYTHON!")
[1] title1 : HELLO PYTHON!

In [18]: t_dict={"num":101,"title":"101titlt","text":"101text"}

In [19]: t_dict 
Out[19]: {'num': 101, 'text': '101text', 'title': '101titlt'}

In [20]: testprint1(t_dict)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/hiroshi/<ipython console> in <module>()

/home/hiroshi/<ipython console> in testprint1(num, title, text)

TypeError: %d format: a number is required, not dict

当たり前と言えば当たり前か.
(引数はリスト,タプル,どんなデータ型,もちろん辞書も一つの引数として使う)

組み込み関数

組み込み関数の例としては,(今回使うものとして)type,str,dir,callable関数を紹介


type関数は対象がどんなデータ型なのかを調べる.どんな引数でもいい
typeの結果を使ってデータ型の一致を調べることに使ったりする.
typesモジュールには型の一覧が入ってるらしいのでこれも使える.
4.3.1. type 関数


str関数は対象を文字列として書き出す.
何でも文字列にする.何も無ければNoneだし,モジュールだとどこに存在するかのパスも出てくる
4.3.2. str 関数


dir関数はオブジェクトの属性とメソッドをリストに返してくれる.オブジェクトというだけあって何でもみれる
そのオブジェクトで何があって何ができるのかを調べるときに便利っぽい,もちろんリストが返るので書き出したりもできる


callable関数はあらゆるオブジェクトを引数にとれて,そのオブジェクトがコールされるとTrue,コールされない場合はFalseを返す.
対象がコール(call)可能(able)かを調べることに使える.
コールというのは,呼び出しということで,関数,メソッド,クラスを使えるか訪ねて使えたら使うこと.
コール - 意味・説明・解説 : ASCII.jpデジタル用語辞典
真偽が返ってくるということは,存在するかしないかの判定に使える.


これらの組み込み関数は__buildin__モジュールとしてグループに分けられている.グループというぐらいだから仮想的に分けているだけかな?


getattr関数は実行するまであるかわからない関数名なんかを試したいときに使う.わからない関数名を投げて使えるか使えないか試せる.
と書いてあるけど,実際には複数の不確定な関数名を一つの呼び出し関数で実行したいときに使うらしい.ディスパッチャってやつ.
4.4. getattr を使用してオブジェクトのリファレンスを取得する
例ではテキスト形式がいくつかあって,それを実行させる関数が一つの時に関数名だけを入れ替えて実行できればきれいだよね的な.
getattr関数は,実行できない関数名があるときは例外を出す.例外処理でもいいのかもしれないけど,(テキスト通りw)幸運にもオプションの3番目で関数名のデフォルトを与えることができる.
デフォルトで何を出力させるかが決まってるとかなら絶対指定.
(あと対応できない引数があったらどうなるんだろう?試してみたいけど例が見つからないので後で探すと)


ディスパッチャはこうやるんだーってとても興味津々で見てた.とても強力な関数です.

リストのフィルタリング

次はリストのフィルタリングということで,マッピング(あるデータをリストへ再配置)したデータがあるけど,いらないのといるのと分けたい時に使える方法として
リストのマッピングは3章でやっているので省略.
3.6. マッピングリスト


for文の中にifを入れて条件判定してフィルタするショートカット.
真偽や不等式やら.
4.5. リストをフィルタリングする

この行はこうだ

methodList = [methodfor methodin dir(object)if callable(getattr(object, method))]

で,変数methodListに入れたいのは,実行可能なメソッド名?のリストを入れたい.
リストのフィルタとcallableの判定を組み合わせるとこうなる
dir()で属性全てリスト化
リスト化した属性の名前でどれがコール可能か,getattrでオブジェクトとメソッドの名前を入れて,callableで実行可能かを調べる
callableの結果をみてフィルタリングリストを使って実行可能なメソッド名をリストに入れていく.
とても濃縮されたコードだなーと.まだぺーぺーな人が言うのもアレですが,奥が深いなあと.


目次みたいなリストができたところで次の行,次のページ.

and-orトリック

andとorを使うと三項演算子が作れるらしい
どちらも論理演算だけど,返すのは値らしい.
これを使うとCやJSなどなどでおなじみな三項演算子が作れる.

使い方
4.6. The Peculiar Nature of and and or

andの性質

  • andは「〜または〜」,全てT(True)ならT,どれかがF(False)ならF
    • T+T=T, T+F=F, F+F=F
  • 値は左から右に真偽で評価される.
  • 全てtrueなら最後に評価した値を,どこかでfalseを出したらその地点の値を出す
    • falseとなる値は,0,'',"",[],(),{},None (数字のゼロ,文字列が何も無い,空のリストとタプルと辞書,ヌル値のNone)

orの性質

  • orは「〜のどれか」,一つでもTならT,全てFならF
    • T+T=T, T+F=T, F+F=F
  • 値は左から右へ評価される.
  • 全てFalseなら最後に評価した値を,Tがあったらそれ以降(残り)の値(どんなにTがあっても)は全て無視して現時点のTの値を出す.
    • "a" or {} なら "a","a" or "b" or {}でも"a"
    • falseとなる値は,0,'',"",[],(),{},None (数字のゼロ,文字列が何も無い,空のリストとタプルと辞書,ヌル値のNone)


andはtrueを通してfalseがあるとそれをを保つ,orでtrueかfalseかをはっきりさせる,みたいかなと何となく思った.
そんな仕組みを使うと三項演算式が作れるらしい.正しく動かすためのトリック付き

4.6. The Peculiar Nature of and and or
大事なのは,andとorの真ん中は確実に真にならないといけない.
ので要素が一つ入ったリストにする.orの後もリストにして,結果はリストの0番目(最初の値)を取り出して結果を表示.

ラムダ関数

一行で小さな関数を定義できる,作れる方法だそうで.
4.7. Using lambda Functions

あーすげーなー,よく1行プログラムにも使われたりしていたのを覚えてる.
ラムダ関数とは,式.簡潔に表現できるものに使うとよいらしい.
判定する前に計算をするけど,その計算が簡単なら判定関数の中に入れ込むとか?
いまいち自分もよくわかっていないけど.いまいち用途が思い浮かばず・・・

次の行はこうだ

4.7.1. 実世界のラムダ関数

processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

何をやってるのか
and-orトリックを使って,collapsaの真偽を判定して,後ろの二つの式のどちらかを実行する.
ラムダ関数はブール値としては常にTrueを返すそうです.関数的にはtrueを返しますが,返値(計算結果とか)はどんなものでもよいとか.
このためにラムダ関数を習ったのね.
collapsaはapihelper.pyとこの章の冒頭を見ると,デフォルト値が1でオプションとして0を指定した例があります.

Chapter 4. The Power Of Introspection

def  info(object, spacing=10, collapse=1):

真偽の判定程度に使ってあるとして(0と1のブール値は偽と真),真の場合はorの手前,偽の場合はorの後のラムダ関数を動かす.
偽の場合の関数は,テキストをそのまま出力している関数と見て,真の場合はどうなるか.

(lambda s: " ".join(s.split()))

split関数は簡単に言うと文字列を分解してリストに入れるもの.引数指定で分解したい部分の文字列の指定ができる.
引数なしだと空白(半角スペース,改行(キャリッジリターン),タブ文字(TABキーを押すと入れられる文字))が分割できる.
分割したリストをjoin関数で半角スペースと一緒に結合してる.
こうすると,複数行の文章(改行したやつ)とかを1つの行に形成される.章冒頭のapihelper.py利用例に,collapseの指定で1行や複数行の切り替えができているのはこれがあるから.
processFuncは関数となり,最後の行で利用されます.

最後の行を読み解く

4.8. すべてを一つにする

    print "\n".join(["%s %s" %
                      (method.ljust(spacing),
                       processFunc(str(getattr(object, method).__doc__)))
                     for  methodin methodList])

まぁメソッドの一覧と,その機能紹介を全て出力してる.という感じだそうで.
実行時に引数指定したオブジェクトの全てのメソッドがmethodList内にあるので,それを使って
processFuncという(どう使われるか決まった)ラムダ関数には,メソッドの__doc__,つまりdoc stringを取得してstr関数で文字列に直したものが一つ
そもそも文字列じゃんとだけど,__doc__が無い場合はNoneが返ってくるのでそれも文字列として扱うためにわざわざstr関数を使う
次に,スペースできれいに整形するためのljust関数でメソッド名の長さを調整したものが一つ.
これを文字列整形をしてリストマッピング,join関数で改行を加えてprint時に改行されたメソッド一覧が出力される.

4.9. Summary

終わり

最後の__name__トリックは,モジュールと単独ファイルの実行でどうするか.
単独実行(python apihelper.py)するとdoc stringが表示される.


以上でメモ終わり.どの行もこいー組み合わせでした.