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

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

本記事は当社が発行しているシミュレーションメールマガジンVol.1の記事です。
シミュレーションメールマガジンの詳細・購読申込はこちら のサポートページから

本当に誰でも読める!! 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 を快適に使えるようになるテーマにフォーカスしてお伝えしていく予定です。今後とも宜しくお願いいたします!

豊岡 祥 株式会社 NTTデータ数理システム シミュレーション&マイニング部所属。
S4 Simulation System の開発のほか、機械学習・シミュレーション・数理最適化を幅広く扱い、分野を横断した問題解決に取り組んでいる。
入社後に競技プログラミングをはじめ、PGBATTLE2023にて企業の部団体3位入賞。

著書: 「XAI(説明可能なAI)──そのとき人工知能はどう考えたのか?」リックテレコム
趣味: 合唱
「数理科学の基礎知識」e-book無料ダウンロードはこちら