今までわりとフラットに処理を記述してプログラムを書いていました。言い換えれば、思いつくままに処理を書いていたという感じ。アジャイルどころか、「こんなコードかな?」と思いついたままに、頭の中、思考がダダ漏れるままに処理を記述していたという感じです。プログラムを書いているというよりは、原稿書いてるというイメージだったのかも。
多少なりとも勉強が進んで、これじゃいかんと。別に繰り返し利用する処理じゃなくても、関数で書くようにしてみようと。データも、変数に入れ込むときにいちいち考えながら加工するんじゃなくて、まずは生データをわりとそのまま取り扱うようにプログラムに取り込み(いや、変数に代入するだけですが)、必要なデータはそこから取り出して使うようにしようと。
# 余計なこと考えながらデータを入力すると絶対ミスするからです!
どちらも、あとからプログラムを書き換えたり、読み直すときにわかりやすい構造にしたかったからです。で、できるところからやってみようと思ったわけです。そしたらハマりました……。
配列なのにintってどういうことよ?
今回ハマった沼については、原因は後者でした。読み直すときにどんなデータかわかりやすいよう配列で記述したつもりだったのですが、それがあだとなり……。まだまだ配列はちゃんと理解できてないわーということが実感できた一件です。具体的には、以下のコードです。
# 変数を設定
ringo_int = 300
ringo_float = 256.1
ringo_list = [ringo_int, ringo_float]
# 型を確認
print(type(ringo_int))
print(type(ringo_float))
print(type(ringo_list))
# 値を表示
print(ringo_int)
print(ringo_float)
print(ringo_list)
# 配列から要素を取り出す
print(ringo_list[0][0]) # ここでエラーになるという。どぼじで???
print(ringo_list[0][1])
これは本当にハマったプログラムではなくて、もっとシンプルなプログラムにしてどこが悪いのか洗い出してみようとして単純化した実験プログラムです。でも、これを実行すると17行目で、
TypeError: 'int' object is not subscriptable
が出てしまって、でもどこが悪いの?っていう。元のプログラムでも、上の実験コードでもエラーは同じ。ringo_listは型を確認したって、<class 'list'>
だし、printしたって[300, 256.1]
じゃん? なんでintって言うのよー!
上記のエラーコードで検索すると、「ちょっとコードを書けるようになってくると必ず突き当たるエラーである」的なことが書いてある解説が多く、まったく意外性のない人生であることに落胆(まあ、それは知っていましたが)。でもやっぱり、intではなくlistを扱っているつもりなので、どこをどう直せばいいのかわからない。
1行×n列の特別感
まあ、元のプログラムで最初に取り扱う生データが二次元配列で作るのに向いていたため、どうも配列は二次元というのがなぜか強烈に頭に残ってしまった模様。subscriptが添え字を意味するという解説を目にしたところで、「あれ、二次元じゃないじゃん?」と気がつき、最後のところを
...
# 配列から要素を取り出す
print(ringo_list[0])
print(ringo_list[1])
# なるほど!
とすればいいことにようやく行き当たりました。そこまでデバッグしておいて配列の構造に思い至らないとは、ほとほと自分の頭の固さがいやになりますね。
最後に整理しておくと、このエラーはringo_listが二次元配列ではないのに二次元配列から要素を取り出す書き方をしていたのが原因で出たエラーです。ringo_list[0]
の部分で要素を取り出したときにintの値が返ってきたのに対して、さらに[0]や[1]を付けていたので、整数に添え字は付けられないよ、つまりTypeError: 'int' object is not subscriptable
になったと、このように理解した次第です。ちぃ、覚えた。
でも、1行×n列の配列として扱ってくれたほうが直感的なんじゃないかとちょっと愚痴りたい気もしますが、記述をシンプルにするというポリシーのほうが勝るのかな。愚痴りたいけど、文句を言うつもりはありません。覚えたからもう大丈夫。前を向いて生きていこう。
今後は配列の構造にはもっと意識的になろうと固く誓った在宅勤務の一日となりました。