クラス

pythonの文法って他の言語と比べると不思議に思えるところがあるが、クラスについてもいろいあれ?と思うところがあり注意。

【 目次 】

Pythonのクラス

  • 9. クラス — Python 2.7ja1 documentation

    Python のクラス機構はオブジェクト指向プログラミングの標準的な機能を全て提供しています。クラスの継承メカニズムは、複数の基底クラスを持つことができ、派生クラスで基底クラスの任意のメソッドをオーバライドすることができます。 ...
    通常のクラスメンバ (データメンバも含む) は (プライベート変数 に書かれている例外を除いて) public であり、メンバ関数はすべて 仮想関数(virtual) です。

  • 9. クラス — Python 3.4.3 ドキュメント

pythonのクラスはJavaやC#と異なり多重継承をサポートしている。

アクセス制御は存在せず、すべてがpublicとなる。
クラスに限らずプライベートにしたいシンボルは名前の前に_付加する事で外からアクセスしないほうがいいよという事を明示するコーディングルールになっている。
いわゆる紳士協定というやつ。

9.6. プライベート変数 - 9. クラス — Python 2.7ja1 documentation

オブジェクトの中からしかアクセス出来ない “プライベート” インスタンス変数は、 Python にはありません。しかし、ほとんどの Python コードが従っている慣習があります。アンダースコアで始まる名前 (例えば _spam)...

クラスについて簡潔にまとめてある参考記事を。

クラスの定義

クラスの構文は、以下のようになる。

class クラス名(親クラス):
    クラスの内容(クラスを構成するメンバー)を記述。

Pasonというクラスを定義、
クラスのメンバーとして
other_nameというクラス変数を定義,
クラスの初期化メソッド__init__にてnameとageというインスタンス変数を定義すると、

class Person:
    other_name=u"ヒト"
    def __init__(self,name,age):
        self.name=name
        self.age=age

継承の例

そしてPersonクラスを継承したクラスManを定義するには。

class Man(Person):
    クラスの内容を記述。

空のクラスを定義する。

最も簡単なクラスの記述例として、なにもメンバーを記述しない空のクラスを定義する事もできる。

class MyCls:
    pass

クラス定義のバリエーション

  • 9.3.1. クラス定義の構文 - 9. クラス — Python 2.7ja1 documentation

    クラス定義を if 文の分岐先や関数内部に置くことも、考え方としてはありえます。 ... クラス定義に入ると、新たな名前空間が作成され、ローカルな名前空間として使われます — 従って、ローカルな変数に対する全ての代入はこの新たな名前空間に入ります。特に、関数定義を行うと、新たな関数の名前はこの名前空間に結び付けられます。

if文内のクラスはif文内のコードが実行されたときのみ定義されるという事か、
pythonのコードは実行順に解釈されるので、同じ名前のクラスを再定義した場合は、後から実行されたクラスが有効になる。

# クラスの定義
class MyCls:
    "first define class"
    pass

print MyCls.__doc__

# クラスの再定義
class MyCls:
    "second define class"
    pass

print MyCls.__doc__

# xがTrueであれば再定義
if x:
    class MyCls:
        "if class"
        pass

print MyCls.__doc__

関数内にクラスを定義して、クラスの定義をグローバルスコープから隠蔽する事もできる。

def func(my_name):
    class MyCls(object):
        def __init__():
            self.my_name = my_name
    return MyCls()

my_inst=func("abc")
print my_inst.my_name
print type(my_inst)

実行結果

abc
<class '__main__.MyCls'>


インスタンスの生成

Pythonのクラスのインスタンスを生成するには他の言語のようにnewを使わない。
関数のようにクラス名の後にカッコをつける。

my_inst = MyCls()

しつこいようだが、以下のようにnewを使ってはダメ

my_inst = new MyCls()   # エラー

クラスのメンバー

クラスとクラスのインスタンスののメンバーには、クラス変数,インスタンス変数,インスタンスメソッド,クラスメソッド,スタティックメソッドがある。
pythonは定数を定義できないので、他の言語のようなクラス定数は存在しない。

インスタンスの初期化は__init__という名前のインスタンスメソッド(コンストラクタ)を定義してそのメソッド内に記述する。
クラス内,メソッドの外で定義した変数はクラス変数になる。
インスタンス変数はインスタンスメソッドの内部ではself.を付加して記述する。

class MyCls:
    c_var = u"クラス変数"

    # コンストラクタ
    def __init__(self):
        self.i_var = u"インスタンス変数"

    # インスタンスメソッド
    def i_method(self):
        print u"インスタンスメソッドを実行しました"

    # クラスメソッド
    @classmethod
    def c_method(cls):
        print u"クラスメソッドを実行しました"

    # スタティックメソッド
    @staticmethod
    def s_method():
        print u"スタティックメソッドを実行しました"

my_inst = MyCls()

また、クラスを定義した後でクラス変数を追加したり、
インスタンスを生成した後でインスタンス変数を追加したりする事もできる。

MyCls.c_var2 = u"追加のクラス変数"
my_inst.i_var2 = u"追加のインスタンス変数"

クラス変数やクラスメソッドなどのクラスに付随するメンバーは、インスタンスオブジェクトからもアクセス可能。

# クラスからアクセス
print MyCls.c_var
MyCls.c_method()
MyCls.s_method()

# インスタンスからアクセス
print my_inst.c_var
my_inst.c_method()
my_inst.s_method()

実行結果

クラス変数
クラスメソッドを実行しました
スタティックメソッドを実行しました
クラス変数
クラスメソッドを実行しました
スタティックメソッドを実行しました

クラス変数,インスタンス変数等のクラスやインスタンスの属性については「オブジェクトの属性を操る(1) - 属性へのアクセス」を参照。
クラスメソッドとスタティックメソッドの違い等のメソッドについての詳細は「メソッドオブジェクト(1) 」を参照。

クラスの名前付けコーディングルール

Pythonのシンボルの命名規則は

クラス名はアッパーキャメルケースで、クラスの属性はメソッド名も含めスネークケースで記述するみたい。
アッパーキャメルケースとはUpperCamelCaseのように単語の先頭を大文字で次以降を子文字でつなげて記述する。
スネークケースとはsnake_caseのようにすべて小文字で,単語の区切りをアンダースコア(_)をつなげて記述する。
例えば

class ClassName(object):
    class_var_name = "クラス変数名"

    def method_name(args):
        self.var_name ="インスタンス変数"

のようになる。

アッパーキャメルケース,スネークケースの意味は

そして、スネークケースは小文字で単語を_でつなげる文字列が蛇のように見えるって事かな。

ページのトップへ戻る