関数編からの続きですー。
今回はクラスについて説明するよ!
クラスの定義
まずは基本的な記述方法から見比べてみましょうー。
それほどガッツリと違いは無いので、すんなり読めると思います。
ですが、相違点を述べると結構あるんですよ。。
PHPのコード
<?php
class Hoge {
static private $defaultValue = 'hogehoge';
private $value = null;
public function __construct($value=null) {
if ($value) {
$this->value = $value;
} else {
$this->value = self::$defaultValue;
}
}
public function getValue() {
return $this->value;
}
}
$hoge = new Hoge();
echo $hoge->getValue();
Pythonのコード
# coding=utf8
class Hoge(object):
default_value = 'hogehoge'
def __init__(self, value=None):
if value:
self.value = value
else:
self.value = self.default_value
def get_value(self):
return self.value
hoge = Hoge()
print(hoge.get_value())
書き方
クラスの定義はPHPと同じくclass
を用いて行います。
if文
や関数
と同じく、スコープの表現を{}
ではなくインデント
で表しています。
ここでもクラス定義の最後に: (コロン)
をお忘れなく。
objectクラスを継承すること!
プレーンなクラスを作る場合は必ずobjectクラス
を継承してくださいな。
継承しなくても作れるのですが、継承した方が何かと利点も多いので。
詳しく知りたい方はコチラを参照して下さいな。
Pythonのクラスにはアクセス修飾子はありません!
ソースを見比べて違いが判りやすい所の1つですね。
Pythonにはなんとpublic
等のアクセス修飾子
がなく、基本的には全てpublic
扱いです。
一応、インスタンス変数やメソッドの名前の前に__
をつけるとアクセス出来なくなりますよ。
コンストラクタ
説明するまでもないと思いますが、コンストラクタメソッドの名前
が違います。
PHPは__construct
で、Pythonでは__init__
ですね。
メソッドの引数のselfって何よ。。
「Pythonきもい!!!」 と言われる部分の一つです。。
このself
ってのは自身への参照(自分のインスタンス)
です。
何でそんなことすんのかってのは説明が面倒すぎるので各自ググって下さい。。
ここで重要なのは メソッドの第一引数には必ず自身への参照が渡される という事です。
インスタンス変数とクラス変数の定義に気をつけて!
PHPの場合はstatic修飾子
を用いて定義を分けていますが、Pythonの場合はインスタンス変数
の定義は必ず__init__
等のメソッド内
で行って下さい。
メソッド外
で定義された変数に関しては、全てクラス変数
になります。
下記サンプルを実行すると、Hoge.hoge
は出力されますがHoge.piyo
はエラーになるのが確認出来ると思います。
# coding=utf8
class Hoge(object):
hoge = 'hoge' # クラス変数
def __init__(self):
self.piyo = 'piyo' # インスタンス変数
print(Hoge.hoge)
# インスタンス変数にはインスタンス化してないのでアクセス出来ない
print(Hoge.piyo)
結構見落としがち(忘れがち)なのでご注意を。。
インスタンス変数・メソッドへの参照
これも一目瞭然ですが、PHPの場合は$this->value
で、Pythonの場合はself.value
になります。
アロー演算子
とドット演算子
の違いもあるので、気をつけて下さいねー。
クラス変数
やstaticメソッド
に関してですが、PHPの場合はsefl::$hoge
の様に書きますが、Pythonはインスタンス変数と同様にself.hoge
でアクセス出来ます。
クラスの継承
クラスの継承について説明しますよ。
いつもどおりまずはサンプルコードから。
PHPのコード
<?php
class BaseClass {
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return$this->value;
}
}
class SubClass extends BaseClass {
public function __construct($value) {
$value = $value * 2;
parent::__construct($value);
}
}
$hoge = new SubClass(10);
echo $hoge->getValue();
Pythonのコード
# coding=utf8
class BaseClass(object):
def __init__(self, value):
self.value = value
def get_value(self):
return self.value
class SubClass(BaseClass):
def __init__(self, value):
value = value * 2
super(SubClass, self).__init__(value)
hoge = SubClass(10)
print(hoge.get_value())
継承の記述
クラスの定義の説明でもう既にやってますが、一応改めて説明しますねー。
Pythonでクラスを継承する場合はクラス名
の後の()
内に継承したいクラス名を記述するだけです。
class SubClass(BaseClass):
親クラスのメソッドを呼ぶ
Pythonでは親クラスへアクセスする場合はsuper関数
を使用します。
サンプルではコンストラクタ内で親クラスのメソッド(コンストラクタ)を呼んでいますが、通常のメソッドでも同じ方法で呼び出せます。
super(SubClass, self).__init__(value)
分解すると以下の様な感じ。
super(自身のクラス, 自身のインスタンス).呼びたい関数(引数)
クラスの多重継承
なんとPythonではクラスの多重継承をサポートしています!
何かと便利な多重継承ですが、複雑になりがちなので注意して使って下さいね。
多重継承の記述方法
通常の継承の記述と同じです。
継承したいクラスを()
内に記述するのですが、複数の場合は, (カンマ)
で区切るだけ。
class SubClass(HogeClass, PiyoClass):
コンストラクタが呼び出される順番
ここらへんややこしいので注意です!
まずはサンプルコード。
# coding=utf8
class A(object):
def __init__(self):
super(A, self).__init__()
print('A')
class B(object):
def __init__(self):
super(B, self).__init__()
print('B')
class C(A, B):
def __init__(self):
super(C, self).__init__()
print('C')
instance = C()
Aクラス
とBクラス
の2つを多重継承したCクラス
があります。
これを実行すると以下の様な結果になると思います。
B
A
C
結果を見るとB -> A -> C
の順番で呼び出されている事が分かりますね。
何故、親クラスにsuper関数が書いてあるのか
先ほどsuper関数
は親クラスにアクセスする為のものだよーなんて説明をしましたが、厳密に言うと親または兄弟クラスにアクセス
する為の物なのです。
Cクラス
の親クラスであるAクラス
とBクラス
は兄弟の関係になるので、super関数
が必要になるのです。
多分この説明だとまだピンとこないと思うので、次の説明を見て下さい!
何故、 B -> A -> C の順番になるのか
Cクラス
の定義はclass C(A, B):
という風にAクラス
が先に宣言されています。
この場合Cクラス
の直近の親はAクラス
という扱いになります。
つまり、Cクラス
内のsuper()
はAクラス
を指すことになるのです。
次にAクラス
を見てみると、兄弟の関係にBクラス
が居ます。
super関数
は兄弟クラスにアクセスする為のものでもあるので、Aクラス
内のsuper()
はBクラス
を指すことになります。
残るはBクラス
ですが、Bクラス
に親は居ません。
兄弟の関係としてAクラス
が居ますが、Pythonはお利口なので一度辿った関係は無視
してくれます。
なのでBクラス
のsuper()
が指し示すものは何もありません。
結果として、B -> A -> C
という順番を辿ることになりました。
ちょっとややこしいけど、理解できたかな?
Mixinクラスってやつ
PHPで言う慣ればtrait (トレイト)
に近い物かな?
「また新しいの出てきたよ。。」 と思った方はご安心下さい。
これは只の多重継承
のお話です。
まずはサンプル。
# coding=utf8
class Mixin(object):
def say(self):
print('Hoge!!!!!')
class Human(Mixin, object):
pass # pass は「なにもしないよ」って意味。
class Cat(Mixin, object):
pass
human = Human()
human.say()
cat = Cat()
cat.say()
Humanクラス
とCatクラス
がそれぞれobjectクラスとMixinクラス
を多重継承しています。
もう本当に只の多重継承
なんですが、何故違うタイトルまで付けてもう1度同じ話をするかというと、 複数のクラスに簡単に機能を追加出来るから なのです。
PHPのtrait
も複数のクラスに簡単に機能を付け加える為の機構でしたね。
同じような事がPythonだと多重継承
を用いて表現する事が出来るのです。
Pythonにおける多重継承
の使われ方はMixinクラス
が殆どです。
Djangoとかで使いまくると思うので、ぜひ覚えて下さい!
ちなみに、この例だとMixinクラス
はobjectクラス
のサブクラスなので、Humanクラス
もCatクラス
も以下の定義で大丈夫です。
class Human(Mixin):
pass # pass は「なにもしないよ」って意味。
class Cat(Mixin):
pass
ただの継承の話になっちゃいました。。
まとめ
今回はクラスの作り方と継承について紹介してみました。
できる事が多い分複雑になってる感じはしますが、使いこなせると凄く便利だし楽しいです!
次は何やろうかなー未定です。。