Iteration & Generator
Iteration、エクセラーには反復計算でおなじみの単語だと思う。なので、反復処理をさせる仕組みをここで学ぶわけだ。
例えば、平方数を1から順に出して行こうとするとき、パッと思い浮かぶのは、リスト内包形式を使ったこういうコードになると思うんですよ。
#リスト内包形式 listincl = [x**2 for x in range(1,10)] print(listincl)
結果は以下のように表示される。
[1, 4, 9, 16, 25, 36, 49, 64, 81]
で、iterationとgeneratorを使うとこう表記できるらしいの。
#ジェネレーター i = (x**2 for x in range(1,10)) print(next(i)) #print(i)ではダメ for k in range(9): #iではなくi以外の変数を宣言する必要あってここではk print(next(i))
結果は以下のような感じ。
1 4 9 16 25 36 49 64 81
i=の時点で1から81までの数字はすでにメモリ上には生成されている。だからgeneratorと呼ばれる模様。generatorとリスト内包形式の違いは、カッコ。カッコが違う。とにかくカッコが違う。()カッコを使った時点でgeneratorなので、print(i)とかやってもエラーを食らう。generatorで生成したデータを出すにはnext()関数を使わなきゃいけない。結果の1行目はprint(next(i))の結果で、2行目の4以降はfor文以下の結果。
ざっくりいうと、リスト内包形式はドバッと計算結果が全て吐き出されるのに対し、iteration & generatorを使うと、結果を吐き出すタイミングをコントロールできる、という感じかな。でも、iとxとkと3つの変数を使うのはクソうざいな。
参考にしたのはみんPyではなく以下のウェブ記事。
【Python入門】イテレータの使い方を解説 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
少数の扱いへの怒りと内包表記の実験
こういう事例があったとしましょう。なんPyの238ページあたりを参考にしています。
str_speeds = "38 アホンダラが 42 ボケカス 20 南港に沈めんぞ 40 誰がクマや 39" arranged = str_speeds.split() print(arranged) speeds = [int(item) for item in arranged if item.isdigit()] print(speeds) print("平均は",sum(speeds)/len(speeds))
半角スペースで区切られた文字列と数字のごちゃ混ぜから数字だけを取り出して平均を取ろうという例です。結果はこう出ます。
['38', 'アホンダラが', '42', 'ボケカス', '20', '南港に沈めんぞ', '40', '誰がクマや', '39'] [38, 42, 20, 40, 39] 平均は 35.8
で、これを各数値を小数点を込みのものにすると、isdigitが効かんのですよ。もちろんint()はfloat()に変えたとしても。で、調べていくと、正規表現を使ったクソめんどくさい処理をしないと、pythonでは文字列と小数点込みの数値の混じったリストから数値を取り出すことは不可能な模様。勘弁してくれや…意味がわからん…おっさんの仕事で扱うデータは株価、P/Eとか小数点込みのデータばっかりやぞ…そういう怒りが事例の文字列のチョイスに反映されています。
備忘録:リスト、タプル、セット、辞書
Pythonにあるデータセットの種類と使うカッコの種類(ていうか、これを覚えるためにここにわざわざこのエントリーを書いているんだ)
- リスト:[a, b]
- タプル:(a, b)
- セット:{a, b}
- 辞書:{a:1, b:2}
それぞれの大雑把な特色
- リストとタプルには順序があるが、タプルは変更操作を受け付けず、既存のタプルに新たな要素を加えたいとか中の要素を変更したい場合は、新たなタプルを作るしかない。既存のタプルを操作して新たなタプルを作ることは可能。なのでタプルは変更したくない設定値的なものに使用するのがよいのでは。
- セットには順番もなく、同じ要素を複数持つことはない。なので、おっさん的には使い方が思い浮かばない。おっさんの使うデータは時系列か、ある銘柄に紐付いたデータばかりなので。
lambda式って何ぞ?
みんなのPython(以後「みんPy」と記す)の今5章にとりかかっています。関数型プログラミングについての章な模様ですが、関数型プログラミングとほかのプログラミングの違いがよくわからんのですが、要するにExcelの関数のように、ある特定の機能や手続きを定めた関数を使っていけば、コードが煩雑にならないとかそういうことですわね? エクセラーの自分としてはなんか当たり前のようなことを改めて言われてるような気もしますが、プログラマーの世界は違うんですかね?
で、この章のわりとしょっぱなにlambda式というものが出てきました。
lambda式を使うと、使い捨ての関数を定義できます。式という言葉がついていることからわかる通り、式を使って関数を定義できるのです。lambda式で定義される関数には関数名がないため、無名関数と呼ばれています。
と説明されているのですが、「お前何言ってんの?日本語使ってくれる?」状態です。筆者はおそらく業界的にはわかりやすい説明をしているんだと思いますが、おっさんファンドマネージャーには「は?」としか言いようがありません。
具体例を見るとよくわかるかもしれないなと思って具体例をとりあえず見てみましょう。みんPyの234ページあたりにあるおそらく艦これかなにかをベースにした具体例を入力するのが個人的には辛かったので、より一般的だと思われる塾の成績管理を題材にしたデータに書き換えました。
#塾の4教科テスト成績管理スクリプト #生徒氏名と算国理社の点数 grades = [ ("梅山",65,78,74,95), ("梅岡",100,38,93,21), ("梅田",32,84,47,100), ("呻き",0,23,9,45), ("梅なんとか",82,91,76,97) ] #算数の点数をキーとして降順でならべかえ、合計点を付加 ranked = sorted(grades, key=lambda x:x[1], reverse=True) for x in ranked: print(x[0:],sum(x[1:5]))
呻きさんはえらいダメな点数ですね。こんなんじゃ中学受験諦めたほうがいいと思いますが、それはさておいて、塾でテストをやって、生徒の名前と各教科の生の点数が並んでて、これをランキング表示させたいわけです。上記の例は書いてある通り算数の点数で並べ替えて、合計得点も表示させようとしています。で、ここにlambdaが登場します。
私の超個人的な感覚ならば算数をキーにしたいなら
ranked = sorted(grades, key=x[1], reverse=True)
でいいじゃん、と思うんですがこれだとエラーで通らないんです。xが定義されてないとかゴチャゴチャぬかしやがるわけです。ところがlambda x:をおくことでxがタプルの要素と定義されるようなんです。もうほんと意味がわかんない。とりあえずこれはこういうもんだと思ってゴリゴリ進みます。
あと、lambda式を使えば、最後のfor分のところの表示までもfor分なしで一気通貫できるようなんだけど、個人的には今はいっぱいいっぱいなのでおいおいどうにかします。
追記(2018年1月7日)
自分がlambda式を気持ち悪いと思う理由を書いていなかったというか、思い出して書こうと思いますが。
key=lambda x:x[1]
単純に言うと、lambdaが宣言された後、カッコも何もなくx:x[1]が続く点ですね。自分の直感としてはlambdaが何を指してるのかlambda(x:x[1])みたいにカッコで括れよ!とどシロートとしては思うわけですよ。
おっさんの参考書
Pythonを学習するにあたって以下のような書籍を仕入れました。
まずはこれをアメリカアマゾンから仕入れたものの読む気が起こらず、本棚で腐っています。実に愚かですね。
次にこれを買いました。誰かの推奨があったわけでもなく、Amazonで探していてなんとなくです。でもなんとなく肌に合わず途中で放り投げました。なんとなくですが体系感が薄く、行き当たりばったり的な感じがする点が肌に合わないんだと思います。
次に、初心者向けPython学習サイトで推奨されていたこれを仕入れました。今のところ昨年末から読み進め、5章までたどり着いています。Pythonスタートブックよりは進んでいます。ただし、この本は作者がヲタなのか、サンプルコードが作者の趣味に走ったような事例ばかりで正直入力するのが苦痛です。でも、さすがに3冊目なのでとりあえずこれをコンプリートしようと思いますし、その学習過程をここに買いていこうと思います。
40の手習いはじめます
40のおっさんです。
Pythonの学習記録をここにつけていこうと思います。
自己紹介をすると年齢は40です。
プログラミング経験は遥か四半世紀昔、厨房の頃に親に無理やり買わせたMacについてきたHyperCardでスタックを書いていた記憶はありますね。あとはAppleScriptで自動化はやっていた記憶はありますね。あ、LaTeXは書きますね。Wordより好きです。
でも、大学に入って情報処理の授業で必修だったC言語はもう無理でした。HyperTalkやAppleScriptとはかけ離れた世界の記法、要するに自然言語からの乖離に戸惑い、最終的には違和感だらけで全く身につくことはありませんでした。なんでこんな文法なの? なんで(自分としてはより自然に思う)この記法では詰まって、こんな変な記法でかかなきゃいけないの?と日々疑問、違和感、怒りばかりでした。最終グループプロジェクトも同じクラスのそこそこできるマンたちと組むことにより、全てを彼らに放り投げることで自分は一切の貢献もせず、情報処理はくぐり抜け、その後はプログラミングやコーディングの世界からは遠ざかりました。
その後仕事を始めてからは、Microsoftのプロダクトを否が応でも使うことになりますが、おっさんのいる組織ではEUC(End User Computing)は禁止されています。要するに日々のルーティンの自動化のVBAは組織のプロセスで使うものならば、システム部に依頼をしてシステム部にコードを書いてもらうことが求められます。要するに、属人的なVBAのスキルに依存し、そのVBAできるマンが人事異動や転職で組織を離れても継続的にメンテナンスをするためなので、当然のポリシーでした。なので、おっさん、社会人になってもVBAスキルを得ることもありませんでした。
で、なんで今更Pythonに手を出そうと思ったのか。おっさんは金融業界で運用をやっています。運用といってもクオンツでもなんでもない、ただのジャッジメンタルな株式の運用と分析です。なのでExcelに数値入力ができ、いくつかの関数を知っていれば仕事はまわります。ところがある日、おっさんと同世代の同僚が外資に転職していって、ひさびさに会って飲んだんです。外資とはいっても依頼して自動化処理ソフトを描いてくれるシステム部も、手足になるコーディングのできる若手もない等リソースが限られる中、必要に迫られてたどり着いた先がPythonだったと。そして今ではPythonをデータ処理等さまざまな自分の業務に生かしている、という話を聞いて刺激を受けたからでした。その同僚も理系でもクオンツでもない、ジャッジメンタルな運用マンです。彼がどうPythonを生かしているかとかは飲んでたのであんまり記憶にありません。ただ、おっさんと同世代が新たなスキルを身につけている、ということにショックと刺激を受けたことは確かでした。
なので、最終的にPythonで何をやろうという目的もなくPythonを始めることにしました。
たまたまこのブログを見つけていただいた酔狂な皆様、おっさんと同様に新たなスキルを身につけようとしているおっさんのみなさん、どうぞ暖かく見守ってくださいませ。