本当に誰でも読める!! Pythonソースコードの読み方講座(第1回) Pythonコードの構成要素

  • HOME
  • 本当に誰でも読める!! Pythonソースコードの読み方講座(第1回) Pythonコードの構成要素

本記事は当社が発行しているシミュレーションメールマガジンVol1.の記事です。

シミュレーションメールマガジンの詳細・購読申込はこちら

本当に誰でも読める!! Pythonコードの構成要素

こんにちは。シミュレーション&マイニング部の豊岡です。

S4 Simulation SystemはGUI操作でシミュレーションモデルを構築できることが魅力ですが、ユーザ側でもPythonコードを読み書きできることで実現できるシミュレーションの幅が大きく広がります。
本講座ではノン・プログラマーの方に向けて、Pythonの「ソースコードの読み方」を解説したいと思います。
Pythonはおろか、プログラミング自体の経験が無い方でも「ソースコードを読むことはできる!」ことがおわかりになると思います。 また、コーディング経験のある方でも、このような観点からソースコードを把握しなおすことは有益と思います。

例文

以下はS4のエージェントシミュレーションで現れるコードの一部になります:

ds = []
vs = []
for v, data in g.nodes_iter(data = True):
    if self.inSight(v, p, r = self.r):
        s = p - data["p"]
        d = numpy.sqrt(s.dot(s)) + paths[v][G]
        ds.append(d)
        vs.append(v)

この時点で理解できなくて全く問題ありません! ただ、ソースコードをまっさらな気持ちで眺めると、次の要素に分解できるのではないでしょうか:

  • 単語: vs, ds, g, selfなど
  • 単語同士をつなぐピリオド "."
  • 単語の後ろにつくカギカッコ "[" "]"
  • 単語の後ろにつくカッコ "(" ")"
  • 一部の特別な単語: ここでは for, if があります
  • コロン ":"
  • 演算記号 "+", "-", "="など

今回はこれらの「読み方」だけに絞って解説をしたいと思います。

単語 / 単語同士をつなぐピリオド "."

単語はプログラム上で動作する「モノ」を表し、Python上はすべて同じ「オブジェクト」と呼ばれるものです。 正体は分からなくても、とにかくそういう名前のモノなのだ、と読めば良いです。

単語同士がピリオドで"a.b"のように繋がっている場合、「aが持っているbというオブジェクト」のように読みます。

もし正体を知りたい場合、先頭の単語("a")はソースコードを上にたどって、一番最初に現れたところを確認する必要があります。 いっぽうピリオドでつながった後の単語("b")は「aの所有物」なのでaの仕様をドキュメントなどで確認することで正体を知ることができます。ドキュメントを見ないといけないので、この部分はある意味「わからなくて当然」です。(英文を読んでいて知らない単語が出てきた、くらいのイメージです。)

例文ですとvs, dsは最初に"="を使った文で定義されていることが分かります(空のリスト"[]"というものですがこの詳細は今回は立ち入りません). また、"for"から始まる行に現れる "g"についてはこの中では定義されていないので、この範囲のソースコードより上をみなくては正体が分かりませんが、「"nodes_iter"というオブジェクトを持っている」ということだけは分かります。

カギカッコ "[" "]"

"[]" はオブジェクトの中身にアクセスするための手段で、

a[2]

であれば「aの中身の2番目のオブジェクト」(※ インデックスは0始まりなので、実際には3個目です)

b["dog"]

であれば「bの中身のdogという名前のついたオブジェクト」 のように「読む」ことができます。

カッコ "(" ")"

カッコはオブジェクトに仕事をさせる記号で、仕事をさせるにあたってオブジェクトにはカッコの中身が与えられます。 どんな仕事をしてくれるかは、オブジェクトを定義したとき(造ったとき)に決められています。 ですので、

d = c("dogfood")

のように書くと「cに"dogfood"を与えて仕事をさせる」「仕事の結果(「返り値」と言います)をdという名前で保持する」と読めます。 何が起こるかはcの定義を辿らないとわかりませんが、とにかく「なにかの処理をしているんだ」と思ってもらえたらよいです。

キーワード

最後に、Pythonにはいくつか特別なキーワードが定められています。これらは知識が必要ですが、多くの場合英語から意味を推測することができます。

if a == b: # → aとbが等しければ以下を行う
    c(a)

for a in b: # -> bの中のaそれぞれについて以下を行う
    c(a) # cがaを受け取って仕事をする

import a # -> aをインポートする(他所からaの定義を引っ張ってくる)

True # 真
False # 偽

※ ここの "#" 記号は上記のようにコードにコメントを入れるためのもので、コードそのものには影響しません。

コロン ":"

前節のif やfor の行の終わりにコロンがついており、次の行がインデントされていることに気づかれたかもしれません。 これはPythonの約束事で、このように「コロン+インデント」によってコードがブロックに分けることで、どのかたまりがifやforの影響範囲なのかを示しています(インデントが無いとエラーになってしまいます)。

演算記号 "+", "-", "=" など

これらの動作はケースバイケースですが、基本的には四則演算のようなものをイメージすれば間違いありません。ですので「読め」ます! "="についてはこれまで説明無しで何度か用いてきましたが、「右辺のものを左辺の名前で保持する」という意味になります(「代入」と言います)。

再度、例文

以上を組み合わせると最初の例文もスラスラと「読む」ことができます!

ds = [] # dsという名前で空のリストを保持
vs = [] # 同上
for v, data in g.nodes_iter(data = True): # gのnodes_iterというオブジェクトにdata(中身はTrue)を与えて仕事をさせた各結果(v, data)について以下を行う
    if self.inSight(v, p, r = self.r): # もしselfのinSightに(中略)を与えて仕事をした結果が真であれば以下を行う
        s = p - data["p"] # p からdataの中身の"p"という名前の要素を引き算した結果をsという名前で保持
        d = numpy.sqrt(s.dot(s)) + paths[v][G] # 長いので省略します(!) 
        # ↑ path[v][G]のように複数個のカッコをつなげることも出来ます(path[v]に対して[G]する、と読めばよいです)
        ds.append(d) # dsにdを与えてappendという名前の仕事をさせる
        vs.append(v) # 同上

コードとしてどのように動作するかを理解するにはひとつひとつのオブジェクトを調べる必要がありますが、これはプログラミングそのものが難しいのではなく、仕様を把握するのが煩雑、ということです(知らない英単語を調べながら英文を読んでいくイメージです)。

おわりに

きちんと勉強するのであれば文法から丁寧に蓄積していくのが王道ですが、現在は非常に多くの書籍やウェブサイトで情報を得ることができます。 今回はあえて逆に、「トップダウン」的にどんどんコードを読み進めてみる、という発想を紹介いたしました。これから勉強を始めるにあたって、少しでも抵抗感を和らげることができれば幸いです。

次回以降はPythonの具体的なプログラミング方法について、特に知っておくとS4を快適に使えるようになるテーマにフォーカスしてお伝えしていく予定です。今後とも宜しくお願いいたします!