初心者による初心者のためのPOKECON自動化【構造編】

1.はじめに

この記事は”初心者による初心者のためのPOKECON自動化【基礎編】”の続きとなります。まだ読んでいない方は、ぜひ以下のリンクからどうぞ!

さて、今回は表題の通りPOKECONプログラムを作成する上でどのような構造で書いていけばいいのかを説明していきます。次回の”初心者による初心者のためのPOKECON自動化【実践編】”に向けて書いたものとなっているので、平行して読み進めるのもいいかもしれません。

2.プログラムの構造

2.1 プログラム構造の概要

プログラムの書き方の一例として、以下のようなコードを挙げます(これを実行しても何の動作もしません)。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

###------使用するライブラリの記載------### 
from Commands.PythonCommandBase import PythonCommand, ImageProcPythonCommand
     #プログラム実行やボタンの押下動作、画像認識などに関するライブラリ
from Commands.Keys import KeyPress, Button, Direction, Stick, Hat
     #押下ボタン・方向などに関するライブラリ
import numpy as np


class Sample(ImageProcPythonCommand):
   NAME = "サンプル"  #プログラム名(POKECON起動時に表示される名前)

   ###----初期化の記載(__init__固定)----### 
   def __init__(self, cam):
       super().__init__(cam) #カメラ設定の継承
       self.sample1 = 0      #変数の初期化
   
   ###------メインの処理部(do固定)------### 
   def do(self):
       self.sample2 = 0 #変数の初期化
       sample3 = 0      #変数の初期化

       '''
       ここにプログラムを書く
       ※'3つで挟んだ区間や、#の後ろの文章(1行限り)は処理では無視されるため、
        実際に書くときはシングルクオーテーションは外す
        この機能はプログラムの処理やメモなどを書くときに使うとよい
       '''

   
   ###---自作メソッド記載部(doの前でも可)---### 
   def made_func(self):
       '''
       ここにプログラムを書く
       ※'3つで挟んだ区間や、#の後ろの文章(1行限り)は処理では無視されるため、
        実際に書くときはシングルクオーテーションは外す
        この機能はプログラムの処理やメモなどを書くときに使うとよい
       '''

このままだと要素が多すぎてわかりにくいと思うので、1つ1つ見ていきましょう。

2.2 ライブラリの記載

from Commands.PythonCommandBase import PythonCommand, ImageProcPythonCommand
     #プログラム実行やボタンの押下動作、画像認識などに関するライブラリ
from Commands.Keys import KeyPress, Button, Direction, Stick, Hat
     #押下ボタン・方向などに関するライブラリ
import numpy as np

この部分では、自分がプログラムを書く、あるいは実行する際に使用したいライブラリを記載します。なお、上記のうち上2つはPOKECON用のプログラムでよく用いられるものなので、呪文のように書いておくといいでしょう。これ以外にも、すでにインストールされているライブラリで利用したいメソッドを含むものがあれば記載しましょう(上記3つ目のnumpyがこれに当たります)。
豆知識ですが、「python (実現したい動作)」や「(ライブラリ名) (メソッド名)」で検索すれば、目的の動作を行えるライブラリやメソッドの詳細が大体ヒットしてくれます。また、5行目のように"import ~ as …"と書けば、他のメソッドにおいて、そのライブラリに含まれるメソッドを呼び出す時に”…”の部分で書いても認識されるため、少し楽になります。

例)変数a(=4.2)を四捨五入したいとき
  「python 四捨五入」で検索すれば、四捨五入はnumpyライブラリのroundメソッドで実現できると分かるので、以下のように書く。

import numpy as np   #ライブラリの記載(numpyをnpと省略)

a = 4.2              #aの初期化
b = np.round(a)      #四捨五入処理(npに含まれるroundメソッドに、aを引数として引き渡す)
print(b)             #結果の表示

#実行結果
#4.0

2.3 クラス名や名前の記載

class Sample(ImageProcPythonCommand):
   NAME = "サンプル"  #プログラム名(POKECON起動時に表示される名前)

1行目の"Sample"の部分は、好きな文字列で大丈夫です(なるべく他のプログラムと被らせない)。NAMEはPOKECONの実行ファイルを選択する欄に表示される名前なので、作ったプログラムに関係のありそうな名前にしておくと整理しやすいですね。
なお、エディタなどで編集するとNAMEの左にタブスペース1個分が自動的に挿入されることが多いです。Pythonでは、このタブスペースを利用してブロックを判別しているため、消さないでおきましょう(タブスペースによるブロックの認識は前回記事に同様の記載アリ)。

2.4 初期化のためのメソッド(__init__)の記載

   def __init__(self, cam):
       super().__init__(cam) #カメラ設定の継承
       self.sample1 = 0      #変数の初期化

この部分では、動作に必要な変数の初期化を行うことができます。動作部分に書くと見にくくなってしまうことがあるので、適宜この部分で”self.(変数名)”として宣言すると良いでしょう(selfについては、2.7に記載あり)。
また、上記2行目のカメラ設定の継承部分は必ず入れておきましょう。

2.5 メインの処理メソッド(do)の記載

   def do(self):
       self.sample2 = 0 #変数の初期化
       sample3 = 0      #変数の初期化

       '''
       ここにプログラムを書く
       ※シングルクオーテーション(')3つで挟んだ区間や、#の後ろの文章(1行限り)は処理では無視されるため、
        実際に書くときはシングルクオーテーションは外す
        この機能はプログラムの処理やメモなどを書くときに使うとよい
       '''

この部分では、動作のメイン処理の記述を行うことができます。POKECONでStartボタンを押すと、この部分が上から順に実行されるという認識で大丈夫です。ここでは前回記事で書いた知識を多く使うので、適宜参照してみてください。

2.6 自作メソッド記載部

   def made_func(self):
       '''
       ここにプログラムを書く
       ※'3つで挟んだ区間や、#の後ろの文章(1行限り)は処理では無視されるため、
        実際に書くときはシングルクオーテーションは外す
        この機能はプログラムの処理やメモなどを書くときに使うとよい
       '''

自作メソッドは、メインの処理メソッドや他のメソッドから呼び出されると、一定の処理動作を行ったり、戻り値を返したりすることができます。記述にあたって、メソッド名の後のかっこに引数(”self”に加えて、他のメソッドから引き渡される値)を指定しましょう。
これらの定義したメソッドが呼び出されると、メインの処理メソッドと同様に上から順番に処理が行われます。呼び出したメソッドから戻り値を得たい場合は、”return”によって戻り値を指定しましょう。

例)戻り値のあるメソッドと無いメソッド
  defから始まる部分はメソッドの定義文なので、実際の目に見える処理は11行目の”a = greeting()”から始まっています。

呼び出したメソッド内の処理を上から実行し、returnの後の値を戻り値として変数に代入する
戻り値が必要ないときには、15行目のように呼び出しだけでもOK

実際のところ、この部分をすべてメインの処理メソッドに書き入れてしまっても動作することはするのですが、長文の処理を複数回行うなどの場合にはソースコード自体が非常に見づらくなってしまうため、メソッドを作ってしまった方がスマートにまとまることが多いです。(ただし、あまり多く作りすぎると今度は読み手側が目で追うのが大変になってしまうので、ご利用は計画的に。)
その他にも、メソッドを作成することで他のクラスへ継承できる…などのメリットが多くありますが、話が複雑になってしまうのでここでは説明しません。

2.7 selfについて

POKECONを使っている方で、偉大な先人の方々のPOKECONプログラムを見てこう思った方はいませんか?

なんで変数の初期化で self. をつけてるものとつけてないものがあるの…?

つけてもつけなくても、一応変数としてプログラム上では扱われます。では、つけるメリットは何なのでしょうか?
ということで、 self. の形で宣言するときのいいことを2点挙げます。

  1. 同じclass内であればどこからでも変数の呼び出しが可能
     各メソッド内で self. を付けずに初期化、宣言される変数はローカル変数と呼ばれ、”そのメソッド内でのみ効力を発揮します。そのため、作成したclass全体で利用したい変数は、 self. を用いて変数宣言するほうが便利というわけです。

  2. どのメソッドからも定義できる
     "__init__"メソッド内や"do"メソッド内に関わらず、好きなメソッドから定義可能です。ただし、変数を定義する前にprintなどで使用しようとするとエラーで怒られるので、プログラム序盤で初期化を行うように心がけましょう。

最初のうちはselfの利点は理解しにくいですが、使ってみると意外と便利だったりします(かくいう私もこの前初めて知ったのですが)。
ただし、これらの変数を呼び出すときには宣言したときのままの形(”self.(変数名)”の形)で呼び出さないと、エラーを吐かれます。これはやりがちなミスなので注意しましょう。

3. おわりに

お疲れ様でした!以上が自分がPOKECONのプログラムを書く上でよく利用していた構造に関する知識となります。(私はこのあたりの知識が特にあやふやなので、どこか誤りや誤植がありましたら教えていただけるとありがたいです)
次回は簡単で実践的なプログラムを作成して、ソースコードを作成する過程を実感していただきたいと思います。

↓ 次回リンクはこちら ↓

4. Special Thanks!!

  • こちゃてす様(https://twitter.com/kochatece12 )
     self. に関係する箇所でアドバイスをいただきました。ありがとうございました!

5. 編集履歴

  • 2022/09/12:記事のアップロード

  • 2022/09/14:【実践編】のリンクを追加

この記事が気に入ったらサポートをしてみませんか?