Python基礎 #1 クラスとインスタンス化を完全に理解する

 

エンジニア職の面接で、「Pythonのクラスとインスタンスについて説明してください」と言われて、うまく答えられませんでした。これはまずいです。基本が理解できていないということです。と言うわけで、しっかり理解するために書きました。

 

*このブログは公式チュートリアル、9. Classesの内容の範囲です。

 

オブジェクト指向とは何か?

オブジェクト指向とは、クラスを用いたプログラミングのことです。オブジェクト指向は、以下のように表すことができます。

 

オブジェクト指向 = モノ + アクション
 
 

例えば、

であれば、person(モノ)が、何か言う(say_something = アクション)ことを規定したオブジェクト指向となります。

 

例えば、

であれば、smoke(モノ)が、ある速度で動く(get_velocity = アクション)ことを規定したオブジェクト指向となります。

 

クラスの基本構造

以下がオブジェクト指向のクラスの基本構造となります。

 

① クラス名を書いてクラスを定義します。

 

② 必ずdef __init__(self):クラスを初期化します。                

ここでは第二引数にnameと書き、オブジェクトが初期化される際に引数を渡すようにします。クラスで使う変数は全て、__init__内で宣言します。この場合、nameをself.name = nameとして変数を宣言します。このself.nameのようなオブジェクト自身が持っている変数のことをインスタンス変数と呼びます。

 

③ クラス内で定義される関数 = メソッドを記述します。

メソッドには、必ずselfを引数として渡します。そうすることでメソッドの中から別のメソッドを呼び出すことができます。この場合、say_somethingメソッドの中で、walkメソッドを呼び出しています。

 

④ オブジェクトを作成します(呼び出します)。

person = Person()としてオブジェクトを作成しますが、このクラスからオブジェクトを作成する(呼び出す)操作のことを、インスタンス化すると言います。

 

クラスのインスタンス化について、公式のチュートリアルでは次のように解説されています(9.3.2. Class Objects)

x = MyClass()

creates a new instance of the class and assigns this object to the local variable x.


The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:...


(x = MyClass()は、クラスの新しいインスタンスを作成し、このオブジェクトをローカル変数xに代入します。

インスタンス化の操作(クラス・オブジェクトを "呼び出す "操作)は、空のオブジェクトを生成します。多くのクラスは、初期化された状態にカスタマイズされたインスタンスを持つオブジェクトを作成したがります。そのため、クラスは次のように__init__()という特別なメソッドを定義することがあります。...)

 

以下が全体のコードです。

person.nameのようにインスタンス.変数名と書くことで変数nameにアクセスできます。同様にインスタンス.メソッド名でメソッドにアクセスします。上記では、walkメソッドと、say_somethingメソッドが呼ばれています。*1

 

クラスの継承(Inheritance)

クラスの継承とは、継承元のクラスが持つ機能を共通として持たせ、さらに継承した先のクラスで独自の機能を追加する構文(syntax)のことです。共通する機能を親クラスに記述し、個別の機能を子クラスに記述することで、簡便化します。

*親クラス:base class、子クラス:derived class

 

これについては、"科学技術計算のためのPython入門"の解説が実践的で分かりやすいので、私の方で改変したものを紹介します。*2

① 子クラスの引数に継承するクラスを渡します。

 

② 子クラスで__init__()メソッドで初期化します。

 

super().__init__()親クラスのメソッドを呼び出します

 

④ 子クラスで変数を宣言します。

 

⑤ 子クラスで、eval_forceメソッドを再度定義(オーバーライド)します。親クラスの流体の動きに加えて、HeavySmoke(子クラス)独自の動きを上書きします。オーバーライドされたメソッドが、継承元のメソッドよりも優先されます。

 

全体のコードは以下になります。

 

イテレータ(Iterators)

イテレータとは、特殊メソッド__iter__()__next__()を実装したオブジェクトのことです。イテレータとは、forループのように何かを繰り返させる(ループさせる)という意味です。

 

公式チュートリアルの書き方を見てみましょう。

①まず、Reverse クラスを定義します。コメントに、"""Iterator for looping over a sequence backwards."""(シーケンスを逆順にループするためのイテレータ)とあります。

 

__init__メソッドでは、インスタンス変数 data と index が初期化されています。data はループする対象のシーケンスであり、index はシーケンスの長さとして初期化されています。

 

イテレータ__iter__()の戻り値は、必ずそのイテレータ自身とします。__next__()はループのたびに呼び出されます。

 

__next__() メソッドでは、index が 0 になるまでループを行います。index をデクリメントし、対応する位置の要素を返します。ただし、index が 0 になった場合は StopIteration例外を発生させ、ループを終了させています。

 

ジェネレータ(Generators)

ジェネレータとは、yield文を含むすべての関数のことです。リストやタプルのように、for文で利用できるイテラブルなオブジェクトです。return文のように値を1つ返すのではなく、複数の値を1つずつ作り出す(yieldする)ため、メモリ使用量がリストやタプルに比べて小さいです。*3

 

ジェネレータの作成方法は2つあります。1つがジェネレータ関数、もう1つがジェネレータ式です。

*ジェネレータ関数:full generator definitions、ジェネレータ式:generator expressions

ジェネレータ関数

以下が、ジェネレータ関数の例です。*4

①値を返したい時(yieldしたい時)に、yield文を使用します。

 

②ジェネレータはnext()を使うたびに、中断したyield文から処理を再開します。

 

③1つ目のnext(gen)実行した後、一度処理が中断されます。そして2つ目のnext(gen)を記述すると、n=2の次のn=1から処理が再開されます。

 

④2つ目next(gen)が実行された後、関数を抜けることで自動StopIteration送出されます。

ジェネレータ式

以下が、ジェネレータ式の例です。

①リスト内包表記は[]で書きますが、同じ構文で()を使うのが、ジェネレータ式です。

 

上のコードでは、要素が1つなので分かりにくいですが、ジェネレータ式の場合、各要素が必要になるまで計算されません。もう少し詳しくジェネレータ式を見てみましょう。

②要素が5つあり、各要素が必要になるまで計算されないので、genを見てみるとジェネレータオブジェクトが返ってきます。

 

リスト化すると、最後の要素まで計算されます。

 

あと2つほど、公式のサンプルを見てみましょう。*5

1つ目は、文字列を逆順にするジェネレータ式です。range(len(data)-1, -1, -1)range(len(data)-1, -1)range(3, -1)を表すため、インデックス'3, 2, 1, 0'の順で文字を取得します。 

 

2つ目は、2つのシーケンス seq1 と seq2 から要素の組み合わせを生成し、それらの組み合わせをタプルとしてリストに格納したジェネレータ式です。*6

 

 

yield from式

最後に、yield from式について見ておきましょう。

PEP 380で、yield from式が追加され、ジェネレータがその操作の一部を別のジェネレータに委譲できるようになりました。

 

ジェネレータ関数で書かれた3、4行目をジェネレータ式に置き換えて、yield from式を併せたものが以下です。

 

ジェネレータ関数の短縮形がyield from式で、yield from iterableの形をとります。chain()関数からサブジェネレータの(v for v in iterable)に処理を委譲させています。

まとめ

Pythonのクラスが説明できないとは本当にひどいです。記録ではPythonだけで1,000時間程学習していますが、構文がごっそり抜けています。動画教材を見てやった気になっていました。動画は副教材で、動画:テキスト=3:7 くらいにしないと、理解してないですね。

 

あとクラスで残っている項目は、以下でしょうか。後日まとめたいと思います。

  1. コンストラクタとデストラク
  2. プロパティ
  3. 抽象クラス
  4. 多重継承
  5. デコレータ 
     - クラスメソッド
        - スタティックメソッド

 


参考文献

*1:シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全』、酒井 潤(2022)、KADOKAWA

*2:"科学技術計算のためのPython入門"、Tetsuya T(2021)、Udemy

*3:Python基礎&実践プログラミング[プロへのスキルアップ+プロジェクトサンプル]』、Magnus Lie Hetland、武舎 広幸(2020)、インプレス

*4:Python実践入門 ── 言語の力を引き出し、開発効率を高める』、陶山 嶺(2020)、技術評論社

*5:9. Classes — Python 3.12.2 documentation

*6:Functional Programming HOWTO — Python 3.12.2 documentation, Python Software Foundation.

アメリカの大学院のCS修士課程入学までのノウハウ(オンライン)

 

タイトルの通り、2023年9月(2023 fall semester)から、アメリカの大学院のオンライン・コンピュータサイエンス修士課程(MSCS)に在籍できることになりました。IELTSを勉強し始めてから入学まで2年2ヶ月と、それなりに時間を費やしたので振り返っておこうと思います。今後リモートでの学位取得は増えてくると思うので、参考にしていただければ幸いです。

分かりやすいよう、まず時間軸を示しておきます。

ご覧のようにやることがいくつかあるので、タイムマネジメントが重要になってきます。以下のようなツールを使って時間を計ることをオススメします。例えば、IELTS○○時間のように可視化することで計画も立てやすくなります。

また、そもそもまとまった時間を確保できるかが問題となってきます。正社員を辞める、という方法は絶対にオススメしませんが、それ以外の時間確保の方法は読者の裁量に任せます。私の場合、2021年からコロナで勤務先がほとんどリモートになり、また、2023年から長期で育休が取得できたことも大きかったです。

 

 

Read the rest of this article
Purchase and read the full article