LoginSignup
39
41

More than 5 years have passed since last update.

PHPerの為のPython入門 - クラス

Last updated at Posted at 2014-05-11

関数編からの続きですー。
今回はクラスについて説明するよ!

クラスの定義

まずは基本的な記述方法から見比べてみましょうー。
それほどガッツリと違いは無いので、すんなり読めると思います。
ですが、相違点を述べると結構あるんですよ。。

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

ただの継承の話になっちゃいました。。

まとめ

今回はクラスの作り方と継承について紹介してみました。
できる事が多い分複雑になってる感じはしますが、使いこなせると凄く便利だし楽しいです!

次は何やろうかなー未定です。。

39
41
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
41