CDとかメモリープレイヤーとか1台でやっている小さな公演チームがあるのですが、機器トラブルが多いのです。
それで、Raspberry pi2を使って、そういうところで使えるような再生機を作れないかとあれこれ試し中です。
Volumioを使って、USBオーディオI/F使って、LCD付けて、スイッチ付けて、でできそうです。
実際の再生はmpdにやらせて、コントロールはmpcでします。
スイッチとmpcを関連付けるのとLCD表示は、Pythonで書かなければいけませんが、ネットで探すといろいろあるようです。自分でいちから書く必要はなさそうです。
ただし、舞台で必要な動作はホームユースのAV機器とはだいぶ違うので、そこは自分で考えなくてはいけません。
そういうわけで久しぶりにPython(2.7です)をさわりました。
最近はすごいH本を読んでいたせいですっかり頭が関数方面にもっていかれてて、先人のオブジェクト指向なちゃんとしたコードがうまく頭に入ってきません。
そのうちなぜかlambda式が可愛く思えてきました。
lambda式でどこまでいけるか?試したところをメモっておきます。
lambdaはダメな子?それとも...
lambdaはPython的な意味での文が使えない。つまり
- 代入ができない
- if:~elif:~else:とかforループとかwhileとかが使えない
- printできない(python2.7ではね)
という制限がある。大きな関数を書くようにはできてないようです。
でもこれって?関数好きにはたまらない仕様なんじゃないの?
まず、代入から。
ブロックの中での代入はできませんが、デフォルト引数の仕組みを使って、名前に式を代入(束縛)しておいてブロック内で使うことはできるようです。
単純な例。ちなみに()かっこでくくると改行は自由です。そこも気に入った。
func=(lambda x: #一番外側。
(lambda y=x+1: #内側一つ目。外側の引数を参照
(lambda z=x+y: #内側二つ目。外側の引数を参照
x+y+z #式本体。
)() #内側二つ目のlambda式をデフォルト引数のまま実行
)() #内側一つ目のlambda式をデフォルト引数のまま実行
) #一番外側のlambda式の定義。ここまで
内側のlambda式からは自分より外側の引数や変数が使えます。
lambda x=1,y=x: のようにすると、yは隣のx=1でなく自分より外側にxを探しに行ってしまいます。
関係ない同士の引数は同じlambda式内に。参照関係がある場合は段を変えて。
段数は必要に応じて増減します。
ちなみに一番外側の引数には定数以外の動的なデフォルト引数を設定しないほうがいいようです。最初に生成した時のデフォルト値が記録されてしまって、大概思った通りの動作になりません。
ループ
引数にリスト内包表記がセットできるし、式本体内でも使えます。
再帰も普通にできます。
逐次実行
実行といっても二種類あります。
- 純粋に計算する
- その他(スイッチの状態を読み取る、他のプログラムに命令する、LCDに表示するなど)
純粋な計算については、代入ができないため、ある式の実行結果を別の式に渡す手段がありません。なので考える必要がないようです。
その他の不純な?動作は順番に実行することがありそうなので、できたほうがいいです。
(A,B,C,...)としておくとタプルの中味を順次評価してくれます。返り値はこのタプル全体。
(A,B,C,...)[-1]とすると最後の要素が最終的な返り値になります。不純な動作をしつつ最後に返り値を純粋に計算するというようなときにも使えます。
条件分岐
if:ブロックは使えませんが、A if B else C は使えます。
同じことがand/orを使ったショートカットで B and A or C とすることができます。
条件が先に来るので読みやすく書きやすい。
ただし、and/orを使う場合はbool(A)がFalseになると期待した動作になりません。
ここまでのことを使えば、結構複雑なこともできると思います。
試しに有名なところでクイックソートとか書いてみました。
lambdaで書くと
qs=(lambda xs :
(lambda le = [x for x in xs[1:] if x<=xs[0] ] ,
gt = [x for x in xs[1:] if x>xs[0] ] :
[] if xs == [] else
qs( le ) + [ xs[0] ] + qs( gt )
)()
)
インデントっぽく見えるように改行しています。
defで書くと
def qs( xs ) :
le = [x for x in xs[1:] if x<=xs[0] ]
gt = [x for x in xs[1:] if x>xs[0] ]
if xs == []:
return []
else:
return qs( le ) + [ xs[0] ] + qs( gt )
どうでしょう?同じに見えます?違って見えます?...って同じですけど...
あとは好みの問題でしょうか...
次回はちょっと闇に踏み込んで。
コメント
コメントを投稿