一般社団法人Pythonエンジニア育成推進協会(以下、当協会)の顧問理事の寺田学です。私は試験の問題策定とコミュニティ連携を行う立場です。 Pythonは学習し始めたばかりの段階でオブジェクト指向を知らなければ勉強ができないというものではなく、クラスやオブジェクトを意識しなくても使いこなすことができます。しかし、今後、フレームワークを使用して何かを作りたいと考えているのであれば、クラスやオブジェクト指向について理解しておいた方がスムーズに進むのは確かです。 そこで前回に引き続き、今回も実践試験の範囲であり、主教材の4章にも掲載されている「クラス」や「オブジェクト指向」のお話の中から、特殊メソッドとデータ型の保証についてお話ししたいと思います。 Part.1についてはこちらからご覧ください。
Pythonの組み込み関数と演算子の挙動を決める特殊メソッド
メソッドにはいろいろな種類がありますが、その中でも特殊メソッドという前後を「__(アンダースコア×2)」で囲まれた、Pythonの組み込み関数や演算子などの挙動を決めるものがあります。 組み込み関数や演算子のそれぞれに対して呼び出される特殊メソッドは決まっており、オブジェクトに与えられる影響は特殊メソッドで決められていることがほとんどです。 Pythonでコーディングする際においてはそこまで重要なことではありませんが、ある程度、特殊メソッドを理解しておくと、なぜその関数や演算子がそういった動作をするのかといったことを理解できるようになります。
メソッドの種類
ここではいくつかのメソッドを簡単にご紹介します。
①初期化するためのメソッド(コンストラクタ):__init__
もっともよく知られる特殊メソッドで、インスタンス化されるときに設定された初期値に基づいて初期化されます。
インスタンス化される時に呼び出され、メソッドの定義は[def __init__(self, 引数):]と続きます。ここで設定された第二引数以降が、インスタンス化される際に引き渡されることで初期化が実行されます。
②len関数で呼び出される特殊メソッド:__len__
リストの要素数や文字数などを調べるlen関数の挙動は特殊メソッド[__len__]で定義されており、strやlistなどの要素数が返されるようなものには必ず[__len__]が定義されています。
len関数が呼び出されると[__len__(self):]が呼び出され、要素数などの適切な値が返されるような仕組みになっています。
③足し算(+)に定義されたメソッド:__add__
足し算(+)をする際にはこのメソッドが呼び出されます。
たとえば、1+2という計算をしたいケースでは、[1]というint型のインスタンスに対して、[__add__(self,引数)]の引数に[2]が入れられて実行されているということになります。
これによって、selfのデータ属性と2の引数を足し算した結果を返すという処理が内部的に実行されます。
ちなみに「==」によって比較する場合は、[__eq__]が呼びだされ、インスタンス自身(self)と引数に入れられた比較対象との比較が実行されるように実装されています。
データクラスによってデータの型安全を図り、データ型を保証する
Pythonにおいては必ずしもクラスを使って書いていく必要はないという話をここまでしてきましたが、Python3.7でデータクラスが導入されてからは、データを独自のオブジェクトにするというケースがここ最近、非常に増えてきています。 こういった手法を取られるケースが増えた理由には色々と事情があると思いますが、データがどういったものであるか、そしてそのデータの型をチェックして、しっかり認識して書いた方が、自分の思うようなオブジェクトを作れるようになりますし、後々汎用性が高く非常にわかりやすいという考え方が浸透してきているのだと考えています(もちろん、使い捨てのプログラムであればそこまでする必要はありませんが)。
今回はデータクラスの細かい話はしませんが、データクラスを使って独自のオブジェクトが書けるようになれば、簡潔にクラスを定義できるようになりますし、より使いやすいものにすることができるようになります。そこで最近積極的に使用されているのがmypyという型安全の静的チェックを行うライブラリです。これはデータ型に格納されている中身の厳密なチェックはされませんが、使用することで型安全に持っていきやすくすることができます。
たとえば、関数の戻り値にユーザーを表すような辞書(dict)として加工して返す、またはjsonで来るものを辞書型にして返したいといったときに、数値が入るべきところにきちんと入っていることを保証したいケースが出てくることがあります。 この場合、どこかで適切なチェックをして、データを格納させるということをしないといけません。このオブジェクトにどういう属性があるのか、保証されているものは何かといったことが不安になることがあります。これは特に、大規模なプログラムや、受け渡すデータ量が多いプログラムの場合に起きがちです。
こう言ったケースでデータクラスを使っておけば、ファーストネームならstr、ラストネームならstr、年齢ならintというようにデータを格納するためのクラスをあらかじめ定義し、その定義に沿わないデータを作らないようにしてあげることができます。また、定義をみればそのデータがどういったものかがわかるにようになりますので、引数や戻り値で引き回されたときに安全に使えるという保証にもなります。
Pythonも以前と比べ型チェックをするような仕組みになってきているため、辞書型で渡していたものの型チェックには別の方法もありますが、データクラスを使った定義と、そこからインスタンスに受け渡すという手法を取られることが増えていますので、現状ではその流れに合わせていく方がいいと思っています。 もちろん、これを初心者が最初から意識して書けるかは別問題ですが、意識できるようになれば、そのオブジェクトがどのような特徴を持ち、どのような操作ができるのか、できないのかを理解できるようになりますし、適切なデータの受け渡しができるようになりますので、メンテナンスしやすい、より一層良いコードが書けるようになります。
さいごに
実践試験の本でも書きましたが、Pythonはマルチパラダイムであるからこそ、様々な書き方ができますので、最初からオブジェクト指向を学ぶ必要がないのは確かです。ただ、次の段階に進む、または実践試験に挑戦するのであれば、クラスやオブジェクト指向は避けて通ることはできません。 オブジェクト指向のようなひな形を考えて何かを実体化させるという考え方自体は普段の生活においてはわかりやすいものではないと思いますが、プログラミングを書く上では非常に重要な考え方になるので理解した方が良いでしょう。
本稿で出てきたような、[self]を書くことの意味や、特殊メソッドの種類、それぞれが持つ意味のすべてを知っておく必要はありませんが、どういったものがあるかをある程度知っておくことで、特殊メソッドの重要性や、関数などがなぜそういった挙動を取るかが理解できるようになります。 Pythonにおいてクラスは要らないという意見も確かにありますが、そんなに嫌わずに、どこかでぜひクラスに触れ、徐々にでも理解していってもらえるといいと思います。
現在、全国でベータ試験実施中のPython3エンジニア認定実践試験では、「クラス」や「オブジェクト指向」も試験範囲となっており、主教材の4章でも掲載されていますので、ぜひより実践的な学習や試験に挑戦していってもらえればと考えています。
[PR]提供:Pythonエンジニア育成推進協会