読んで欲しい人
- python初学者でシーケンス(listやtupleなんか)、条件分岐ぐらいまで終わった人
- 超初級を脱出したい(自分も同様w)
- __iter__って何?iterableとiteratorって何が違うのって人?
連載項目
- iteratorの理解を深める
- generatorの理解を深める
- decoratorの理解を深める
- 特殊メソッド・属性に慣れる
- ポリモーフィズムに慣れる
目標は一旦終わった段階で以下のようなステータスになっていることです。
・pythonのチュートリアルが終わった感じのレベル ・iterater/generatorといった生成機っぽいやつにパッとみの辛さを感じない ・printしたらobj instanceが返ってくるという悲しい展開からの脱却 ・特殊メソッドやプライベート変数とうに少し慣れる(呼び出しの概念が少し理解できた感じ) ・ポリモーフィズムを自分で作れる感じ(ただし、非常に簡単なやつ)
特殊メソッドを理解すると何ができる?今回の記事のゴール
特殊メソッドとは、__XX__で定義されるメソッドのことをいいます。全ての特殊メソッドを把握することは容易ではないので、実際は一つづつ理解して行くとともに、自分でも作れるようになっていくことが次のステップには必要です。
主な利用目的はオブジェクト自体に特殊な挙動を持たせたい場合や、オブジェクトの振る舞いを変更したい場合などに使用します。
聞くより慣れろで、代表的な特殊メソッドを少しみていきます。
代表的な特殊メソッド
__init__(self,)
最もよく利用されるのは、class設定時に利用する__init__()でしょう。用途としては初期化ですね。
__init__はコンストラクタ(正確にはイニシャライザと呼ぶのが正しい気もしますが、イメージしやすいように)と呼ばれるもので、インスタンスが生成されたタイミングで、呼び出し元に返される前に呼び出されるものです。
一般的にはnewでオブジェクトを作成して、__init__などでコンストラクト(内容作成みたいなイメージ)していきます。
pythonでclassを利用してオブジェクトを作成する場合、最初に呼び出しをしますよね?クラスはあくまでオブジェクト設計用の設計図だとよく入門書に書いてあったと思います。
class Person:
def __init__(self, name="aa"):
self.name = name
person1 = Person()
print(person1) #<__main__.Person object at xxxxxxx>が返される
person1.name = "bb"
print(person1.name) # bb
このperson1 = Person()の部分でオブジェクトを作成し、person1.name = “bb”でname属性を与えています。
算数用(算術演算子)を定義する特殊メソッド
class Cals():
def __init__(self,value):
self.value = value
def __add__(self,other):
return self.value + other.value
def __sub__(self,other):
return self.value - other.value
def __mul__(self,other):
return self.value * other.value
def __truediv__(self,other):
return self.value / other.value
def __floordiv__(self,other):
return self.value // other.value
cals1 = Cals(10)
cals2 = Cals(20)
print(cals1 + cals2)
print(cals1 - cals2)
print(cals1 * cals2)
print(cals1 / cals2)
print(cals1 // cals2)
class Calsで定義した__add__, __sub__などが算術演算子用の特殊メソッドです。+処理したときに、__add__が呼び出されている形です。
__doc__を利用してクラスの内容を確認できるようにする
class Cals():
"""Calsクラス
算出演算子の特殊メソッド一覧
"""
def __init__(self,value):
self.value = value
print(cals1.__doc__)
#Calsクラス
# 算出演算子の特殊メソッド一覧
通常クラスを設定すると、最初に各クラスの内容(属性やメソッド等)について、docstringを作成します。上の場合、”””Calsクラス 算出演算子の特殊メソッド一覧”””というクラスの定義だけコメントされています。
このコメントされた部分を呼び出す際に利用するのが、object.__doc__となります。
ついでにprivate変数も
特殊メソッドでよく使うものには、getter/setterとよばれる類の物があります。これに軽く触れるために、その大前提となるクラスでのプライベート変数を少し説明します。
真面目に全部(関数での呼び出しやクラスない呼び出しなど)のパターンを説明していると、それだけで一記事できるくらいですので、細かい点は皆さんで実際に作りながら勉強してみてください。「初心者のためのpythonプログラミング入門」の補強編に説明がある程度のパターン入っていたので、下記リンクからそちらを買ってもらってもいいかと(390円とかで安かったので)
プライベート変数って何?
プライベート変数とは、変数の頭に__(アンダーバー2つ)がついている変数のことで、この形で宣言するとクラスないのプライベート変数となります。基本クラス外から関与できない変数が作られます。なんの意味があるのと思われるかもしれませんが、実際開発していると他の動作で変数を変えられたくない場合などはprivate化することがベターです。
でも、そうすると呼び出しや書き込みはどうするのでしょうか?そこで利用するのが、getter/setterです。(ここら辺の話は前回のデコレータの絡みでもあります)
getter/setterって何?
聞くより慣れろで、以下のサンプルをみてみましょう。本当は一旦この前にprivate化させた属性にクラス外からアクセスして弾かれることを確認してからやるべき物なので、そこは皆さんやってみてください。
class Test:
def __init__(self, pub_val="pub", pri_val="pri"):
self.pub_val=pub_val
self.__pri_val=pri_val
def set_private_val(self, pri_val="pri"):
self.__pri_val=pri_val
def get_private_val(self):
return self.__pri_val
test=Test()
print(test.pub_val) #pub->普通にpub_valが取得される
print(test.get_private_val()) #pri-> get_private_val経由で、取得できる
test.set_private_val("PRI") #->セッター経由で値を入れ込むことが可能
print(test.get_private_val()) #PRI
ちなみに上記で、test.pri_valもしくはtest.__pri_valとかでアクセスしにいくと、アクセスできないはずです。それも試しながら、getter/setterがクラス内部から、private変数にアクセスしているという意味を体感してもらえるといいかと思います。
まとめ
四方八方に話が飛んでしまい、ゴールが見えなくなってきたので、一旦ここらで特殊メソッド関係をおしまいにしてみました。かなり消化不良かと。。
個人的にはある程度書いて慣れて、挙動が理解できない時にブログ等で理解するとより理解が進むと思っているタイプなので、ぜひ自分のローカル環境等で試してみていただいて、実際の挙動をみてみてください。
コードは書かずに覚える物でもないと思っていますので、一旦書いてみてつまずいて、そこで勉強して、土台を少しずつ強くしていきましょう。(私も現在進行形でそうですw)
連載目次: python超初級脱出シリーズ
pythonの入門編を終えた後に、supper_beginnerクラスを脱出するためのシリーズです。unitテストやフレームワークの使い方に行く前に、少しpythonの知識を深めたい人用の記事です。