新年度になったということで、少しブログの書き方を変えようと思います。
このブログではPythonについて色々書いていますが、Pythonはオブジェクト指向の言語なので、オブジェクトと言う多飲医で管理できるようになっています。今回は、そのクラスについて書こうかなと思います。
回路とプログラミング
従来のプログラミング言語は手続き型なので、上から順番に処理をしていく流れになっています。この構造は 【 順次 】 の構造になりますが、手続き型の言語でも 【 処理の塊 】 を用意して、その単位でコードを書き、その処理の塊をコードの中で順番どおりに行うことになります。
この考え方は、電子部品の組み合わせで出来上がったモジュールを回路の中に実装して直列回路で実行するのと同じ考え方ですが、直列回路で処理を行う際には、電流の流れに沿って順番を決める必要があります。コードを書く際の基本的な考え方は、この回路の中のモジュールの並びと同じなので、
■ モジュールの処理の内容を作る
■ モジュールの実行の順番を決める
という2つの流れで処理を実装することができます。この構造が直列回路で構成された回路の挙動になります。
この回路をスイッチで動かすと一度だけ動作して、通電後にはラッチのように働くので、動作後の状態が維持されるわけですが、基本的な構造は豆電球のような発光体の挙動で考えるので、通電後にモジュールの挙動があった場合、その終了後の状態が維持されることになります。
この状態が維持されると、メモリーモジュールと同じ挙動になりますから、回路で実装した処理を繰り返して実行する場合には、
■ 実行
■ リセット
を繰り返して実行することになります。こうした処理を実装する場合にはタイマー回路を実装することになりますが、マインクラフトのレッドストーン回路も二値論理で動作していますから、クロック信号を発生させるクロック回路を作ることでループ処理を実装することができます。
つまり、直列回路を用意してその中にクロック周波数の発生をする構造を作ると実装された処理が連続して実行されるので、回数の指定などを行わない条件だと無限ループを実装することが出来ます。
このように
■ 通電の維持
■ 通電と遮断のループ処理
によって回路内の挙動が変化するわけですが、この挙動は
■ メモリーの挙動
■ タイマー回路の挙動
になります。このように処理を繰り返す場合には、
■ 実行する処理の実装
■ 実装した処理のループ処理
を行う構造にする必要があるのですが、この状態だと前述のように無限ループになってしまいます。この状態だと 【 指定回数分だけループする処理 】 の実装ができませんから、こうした処理をする場合には、 【 判定 】 を入れる必要があります。
回路を組む場合には必ず 【 主電源 】 を用意しますが、この際に
■ オン
■ オフ
のような通電の有無を指定する切替器を用意します。これがスイッチになりますが、此の時の処理を二値に置き換えると、
■ オン : 1
■ オフ : 0
の状態になります。この場合、
■ 回路1の挙動 : 通電
■ 回路2の挙動 : 遮断
と考えることができますから、この構造は 【 並列回路の挙動 】 になります。
この並列回路の挙動の条件を追加して分岐の選択肢を与えることで、路の中に条件分岐を実装することができます。
高校の物理では半導体が登場しますが、これは、絶縁体のシリコンに導体の特性を追加したものになります。シリコンに不純物を混ぜることで電子の移動が
■ 流入
■ 流出
するような仕組みになった構造にすることで、電流のコントロールが出来るようになります。半導体には
■ N型半導体
■ P型半導体
がありますが、この異なる半導体を張り合わせると、電流の流れが一方通行になるので、電流の流れを決めることができます。このN型とP型を張り合わせた物が 【 ダイオード 】 になります。ダイオードは過電流が流れると壊れるので、電気抵抗と組み合わせて使用するこちなりますが、電流の流れを一方通行にしたい場合に使用することができます。
また、片方の半導体をもう片方の半導体で挟むと、電流の流れで回路の切り替えが出来るようになりますが、この構造は並列回路の切り替えなのでスイッチとして使用することができます。この構造のものをトランジスタといいますが、市販の製品のFETと言う名称の製品がトランジスタになります。
トランジスタもダイオードと同様に過電流が流れると壊れるので、電気抵抗とセットで使うことになりますが、これを使って論理ゲートを作ると
■ 放熱
■ 消費電力
が高くなるので、集積回路では不要な時に電流が流れない構造にして少電力な構造のものが使用されています。この構造がMOS構造になります。その為、ロジックICのようにNANDベースのものについても電気抵抗とトランジスタの構造ではなく、MOS-FETが使用されています。
ちなみに、トランジスタによって使用できる電流の大きさが異なるのですが、トランジスタ単体だと熱を持つのでパワートランジスターでは、ヒートシンクがついていますが、電流が大きくなるほどヒートシンクのサイズが大きくなっています。
電子パーツについては、
の中でも触れていますが、電気工作で使用する部品には、
■ 表面実装
■ 裏面実装
のものがあるので、ソルダリングペーストを置いてその上にパーツを配置して熱ではんだ付けするのが表面実装で、ブレッドボードに挿して使うようなパーツは基盤の穴に足を通してウラ面からはんだ付けをするので裏面実装になります。
のあたりのパーツが表面実装で、
のように裏側ではんだ付けされているものがウラ面実装のパーツになります。
分岐の実装にはトランジスタが使用できるのですが、これは、電流の流れで通電する回路を切り替えることが出来るので、手動で行うスイッチの操作のようなものを回路内の電流の制御(なので、電位差の変化)だけで実装できるパーツになります。
このように分岐を入れる場合には
■ 並列回路の構築
■ スイッチ導入
を行うことになりますが、これが回路内に条件分岐の仕組みを実装する方法になります。
この時の判定として論理ゲートを使うことになりますが、プログラミング言語の条件分岐でも、判定に
■ 論理演算子
■ 比較演算子
などを用いるので、
■ 個別の結果の組み合わせ
■ 値の範囲での判定
を行えるようになっていますが、こうした判定も電気工作で作る回路内に実装することが出来るようになっています。
こうした処理ですが、
■ 直列回路 : 順次
■ タイマー回路 : 反復
■ トランジスタ : 分岐
として機能するので、この構造を汎用性がある集積回路を用意してコードで制御をすれば、消費電力とサイズを小さくすることが出来るので、マイコンなどを使ってコードで制御をすることになります。
このように 【 デバイスの制御をする仕組み 】 は、アナログ回路でも制作できるわけですが、この処理をコードで行っているのが 【 プログラミング言語 】 になります。
ちなみに、プログラミング言語の基本部分は中学校一年生の数学の 【 項 】 のカリキュラムで登場しますが、
■ 変数
■ 定数
の特性もこのカリキュラムで登場しますし、 【 処理の塊を並べる 】 という加算の構造でシステムを作る考え方も 【 項 】 の構造そのものなので、その仕組みをプログラミング言語に当てはめて学習すると
■ 変数
■ 順次
を使った処理の理解がしやすくなります。また、
■ 加算 : 順次
■ 係数 : 反復
なので、小学校低学年の算数の段階でこの構造は登場しているわけですが、処理の流れを扱う 【 アルゴリズム 】 についても式の計算とは少し異なる手順を用いる 【 筆算 】 がこれに該当するので、 【 手順を使った処理の方法 】 についても作り方は学びませんが 【 工程の基づいて処理をする方法 】 を扱うことになります。
このように、処理の方法については一般科目のカリキュラムで基本的なことは学んでいる訳ですが、プログラミングという考え方が 【 一つのデバイスで処理の方法を切り替えて異なる処理を実行するための手段 】 になります。
回路で出来ることを汎用し絵のあるデバイスで実行するための指示書を書く作業がコーディングになりますが、そのコードを使うことで指定した内容を実行できるようになっています。
こうした自動処理はオルゴールや手回しオルガンの譜面と同じですが、この処理の内容を楽器の制御ではなく、演算処理によるデバイスの制御で使用しているのがプログラミング言語を使用したコードになります。
手続き型のコード
プログラミング言語の登場当初は機械語やアセンブリ言語ですが、これを人が何をしているのか解る記述ができる物として作られたのがFortrunになります。この言語は手続き型なのですが、処理の塊を作るのに 【 サブルーチン 】 を使用する作りになっています。これは、閉回路であるメインルーチンとは別に特定の条件で動作する別の閉回路を用意しておいて、その間を行き来することで処理の流れを作ると言う考え方になりますが、この概念はBASICにも実装されているので、メインルーチンが重くならないようにサブルーチンを使った処理を使用できるようになっています。
BAISCの場合、インタプリタが一行ずつコードを機械語に翻訳しながら処理を行っているので、無限ループをするメインルーチン自体が重たいと1つのループがひたすら重たくなってしまうので、分岐後に動くようなものだと読み込まずに済むサブルーチンに分けておいて行数を減らして軽くすることができます。実際にはBASICのしよす荒れている時代だと文字の表示も文字列を記述るのではなくVRAMのデータを直接書き込んだほうが速いのでそうした処理を用いることになりますが、この時に使用するのがPOKEやPEEKになります。
このように手続き型の言語でも 【 処理の塊 】 単位でコードを考えて、その処理をサブルーチンでまとめて処理を行うことができるようになっていますが、後に登場するプログラミング言語では、 【 関数 】 を使用することでサブルーチンよりも融通の効く使い方が出来るようになります。
C言語では、main関数と言う優先して実行される関数を使用してコードを書きますが、この構造が関数の仕組みになります。当然、ユーザー関数を作って実行できるようになっていますが、サブルーチンのようにGOSUB〜RETURN間でしか扱えない構図ではなく、 【 関数は何処からでも呼びさせる 】 仕様になっています。
これが手続き型で実装されえている 【 処理の塊を人まとまりにして扱う方法 】 になりますが、C言語には少し複雑な仕組みになりますが、構造体が使用できるので関数とは違った管理を行うことも出来るようになっています。
関数
関数の仕組みは、高校の数学で登場する合成関数と同じ作りになっているので、これも数学と連動して学習するとそれほど難しいものではありません。
コンパイル型言語の場合、組み込み関数を使用する際にも読み込みを行う記述が必要になりますが、Pythonでは組み込み関数はそのまま実行出来るので、コードの記述だけで処理の実装を行うことができます。
Pythonでは、関数は組み込み関数で使用できるのですが、関数は
■ 関数の実装
■ 関数の呼び出し
で使用することができます。合成関数では、
■ 関数 : f(x)=x
■ 処理 : f(1)
のような形になりますが、プログラミング言語だと、この構造は引数を使用した処理と同じになります。
関数内の変数
プログラミング言語も数学と同じで 【 値がないと処理ができない 】 ので値を作ることになりますが、管理をする場合だと、引数の場所をデバッグするよりも引数を変数化しておいて初期化の記述をした場所を書き換えたほうがメンテナンス性が高いので、通常は一番最初に初期化を行います。また、存在しない値は呼び出せないので、使用する値は使用する前に用意することになります。
そのまま記述した場合だと、
■ 初期化
■ 処理
で動くのですが、関数の中で使用している変数についてはブロックスコープがかかって外部から参照できない仕様になっています。
実際に
のような感じのものを使って
のように実行すると
のように変数の値が参照されていないのでNoenが帰ってきます。
このように関数ではブロックスコープがかかるので関数内で発生した変数は参照できないので、これを参照する際には 【 戻り値 】 として出力することになるので、 【 return 】 を使用して関数の実行時に戻り値を出力できるように刷る必要があります。
その為、先程のコードを
のように変更すると戻り値を出力できるようになります。この処理では、
のように 【 return x 】 が追加されているのですが、
のようなコードの構成になっています。つまり、関数部部に外はないも変わっていませんが、これを実行すると
のように関数内の変数が戻り値として出力されているので関数を代入した変数を使用すると戻り値が使用できるようになっています。このコードでは関数の実行結果を表示しているので、取得した戻り値が表示されています。
配列を使う
関数内の変数は単一の値だけでなく配列も使用できるので、
のような形にすることもできます。
のように関数内で配列を作り、それを戻り値で出力するようにして、この関数を変数に代入します。
すると、変数bには戻り値が代入されるので、
のようにインデックスの指定を行うことで配列内のデータを取得できます。実際に実行すると
のように値を取得することが出来るのですが、戻り値で複数の変数の値を格納している場合だとインデックスの指定を刷ることでn番目の値を取得して使用することが出来るようになっています。
この事例では、 【 定数 】 をしよしていますが、任意の値を使った変数での制御も可能です。
引数を使う
関数では、合成関数のように値を取得して処理に反映させて結果を得ることができます。その為、引数を使用することで外部の値を参照して処理を行えるようになっています。
のコードでは、
のように関数に引数を実装して、その引数を参照してリストに格納しています。そして、その値を戻り値として返しています。
そして、この値をiput関数で入力するようになっており、入力した値をそれぞれの変数に格納しています。
この格納した値を関数の引数に代入して変数に代入しています。
この状態にすると、関数内には引数と同じ値が格納されているので、第一引数〜第三引数までの値を使用できるようになるので、これをインデックスで呼び出すkとおでこ別の値を取得できるようになります。そして、この値をprint関数で出力する仕組みになっています。
これを実行するとと入力待ちで文字入力を行い、その値を取得して処理を行うことが出来るので、
のようになります。このように関数を使用すると関数実行時に格納された引数を元に処理を行うことが出来るのですが、これをreturnで戻り値で使用して別の処理に使用することが出来るようになっています。
ここまでが手続き型でも使用できる関数での関数内の変数の取り扱いになります。
オブジェクト指向
Pythonはオブジェクト指向の言語になりますが、こうした言語では、クラスを作ってその関係性を指定することでコードを作る仕組みになっています。
手続き型だとノードやフローチャートだけで構造を考えることが出来るのですが、オブジェクト指向の場合クラスの関係性なので、クラス図を書いて考えることになります。
アプリケーションでは人と作るものの関係性やクラス自体の構造などを考えなければならないので 【 構造物を見る視点 】 によって異なる図を使ったほうがイメージがしやすい場合があります。その為、ユースケース図のようなものも使用することになりますが、こうしたツールがまとまったものが 【 UML 】 になります。UMLはクラス図からJAVAのコードを生成できるものもありますが、クラスを使う場合だとUMLベースで思考をしたほうが処理の流れを考えやすいので、プログラミング言語の学習と同時にUMLも学んだほうが良いと思いますし、そのほうが思考を形にしやすくなります。
クラスについては、関数以上に処理の管理を行いやすくした構造物になりますが、今回は、クラス内の変数を使うことで関数との違いについて触れることにします。
クラス内の変数
関数では、
def 関数名(引数):
処理
と言う形で関数を実装しましたが、クラスの場合だと
class 関数名(引数):
処理
と言う形で処理を実装していきます。クラスには実装できるものが多いので、今回はイニシャライズなどを使わずに最も簡素な構造で書いていますが、基本的な構造としてはdefの部分がclassに変わった構造になっています。
関数ではブロックスコープによって関数内の変数の値の取得ができない仕様になっていますが、classの場合だと少し異なります。暮らすに変数を実装するとクラス内変数として使用できるのですが、この場合、
のようなコードで変数を使用することができます。まず、
のようにクラスの宣言をしてクラスの中で変数の指定をします。これは、クラスの中の変数なので 【 クラス変数 】 になります。これを呼び出す場合には
【 クラス名.クラス変数名 】
で呼び出せるので、
のようになります。これは、モジュール内のメソッドの呼び出しと同じ形になりますが、メソッドの場合、
【 モジュール名.メソッド名 】
で呼び出しますが、記述としては同じような形になります。
そして、この代入した値を表示するので
のようにprint関数の引数に変数を代入しています。これおw実行するとクラス変数が出力されるので、
のように値が出力されます。
変数は複数でも使用できるので、
のようにすることもできます。この場合、
のようにクラス変数をリストにして複数の値を用意して出力を
にしているわけですが、これも関数と同じようにインデックスで値を呼び出すことが出来るので、
のようにクラス変数内の値をインデックスで呼び出すことができます。
また、
の事例のように
のように複数のクラス変数を用意してこれを異なる変数に格納し、
これらをprint関数で個別に表示するように指定します。
すると個別のクラス変数を取得できるので
のような値を取得することができます。
このようにクラスを使うと 【 クラス変数 】 の指定が出来るので、 【 クラス名.変数名 】 の形で呼び出せるので、これを変数に代入することで値を参照することができるようになっています。
関数では、戻り値を使用しないと関数内の変数を使用できないようになっていますが、この変数の状態はJavaScriptのvarと同じで何処からでも呼び出せてしまうものになっていますから、JAVAなどではアクセス修飾子でアクセス制限を書ける仕様になっています。マイクロソフトオフィスのマクロでもPribate/Publicのような指定がありますが、これが
■ 何処からでもアクセスできる
■ アクセスの範囲が決まっている
という指定を刷る時に使用します。JAVAではこの辺りが複数選択できるので参照の範囲を指定してコードを書くことが出来るのですが、VisualBASICもPribate Subのような記述があるので、アクセス修飾子を使った管理が出来るようになっています。
VisualBASICは 【 BASICのコマンドがある 】 のでなにか解る状態でスタートできるのですが、コードの記述が全く違うので 【 別の言語と化している 】 わけですが、クラスを使う場合には通常のプログラミング言語だと何処からでもアクセスしてもらうと困るので、アクセスの範囲指定を行います。
JavaScriptとPythonにはこれがないので、記述で判断できるようにしてコードを書く際に参照の方法に注意して使用することになりますが、この際の目印が 【 _(アンダーバー) 】 の数になります。