読者です 読者をやめる 読者になる 読者になる

Python Works

Pythonで色々プログラミングする

Python入門 - クラス その2

クラス変数

インスタンス変数は、生成されたオブジェクトごとの変数で、別オブジェクトの変数なら、完全に独立した変数でした。

Pythonでは、このインスタンス変数とは別に、オブジェクトではなくクラスに属する変数を作ることもできます。これを「クラス変数」と言います。クラス変数は同じクラスのオブジェクトの間で共有されます。また、オブジェクトを生成しなくてもクラスからアクセスできます。

 

書式

class クラス名:
    クラス変数 = 値

 

サンプルコード

class MyClass:
    value = 100

    def plus(self, x):
        MyClass.value += x
        print(MyClass.value)


print(MyClass.value)

test1 = MyClass()
test2 = MyClass()

test1.plus(100)
test2.plus(50)

 

実行結果

100
200
250

 

 別々に作成したオブジェクトのインスタンスメソッドで個別に数値を足しています。足し算の結果が、オブジェクトごとに別々にならず、累積していっているのがわかると思います。

 

クラスメソッド

インスタンス変数、インスタンスメソッド、クラス変数ときて、最後にクラスメソッドを紹介したいと思います。

クラスメソッドも、クラス変数と同じでオブジェクトを生成しなくても、クラス名から利用することができます。

 

書式

class クラス名:
    @@classmethod
    def クラスメソッド名(cls, 引数):
        クラスメソッドの処理
        クラスメソッドの処理
        ・・・

 

サンプルコード

class MyClass:
    value = 100

    def plus(self, x):
        MyClass.value += x
        print(MyClass.value)

    @classmethod
    def minus(cls, x):
        cls.value -= x
        print(cls.value)


print(MyClass.value)

MyClass.minus(10)

 

実行結果

100
90

 

 クラスメソッドの第一引数は「cls」とします。インスタンスメソッドの「self」と同じで、クラス自身を表していてclsを利用してクラス変数や、クラスメソッドを利用することができます。呼び出す時には、自動的に渡される省略するところも一緒です。

クラスメソッド内では、インスタンス変数を使うことはできません。インスタンス変数はオブジェクトを生成して初めて作られるものです。そのため、オブジェクトを生成しなくても利用できるクラスメソッドの中ではインスタンス変数を利用できないのです。

ちなみに、selfと一緒でclsという名前でないといけないわけではありません。しかし、clsdとするのが暗黙のルールです。

なお、「@・・・」を「デコレータ」と言います。

 

 スタティックメソッド

クラスメソッドに似ているメソッドに「スタティックメソッド」があります。

 

書式

class クラス名:
    @staticmethod
    def スタティックメソッド名:
        スタティックメソッドの処理
        スタティックメソッドの処理
        ・・・・

 

 

サンプルコード

class MyClass:
    value = 100

    def plus(self, x):
        MyClass.value += x
        print(MyClass.value)

    @classmethod
    def minus(cls, x):
        cls.value -= x
        print(cls.value)

    @staticmethod
    def devide(x):
        MyClass.value /= x
        print(MyClass.value)


print(MyClass.value)

MyClass.devide(5)

 

実行結果

100
20.0

 

クラスメソッドとの違いは、引数でclsを渡すかどうかだけです。clsを渡さないため、スタティックメソッドでクラス変数を利用しようと思うと、クラス名からアクセスしないといけません。

クラスメソッドとスタティックメソッドとの動作の違いについては、別の記事で解説しようと思います。 

 

アクセス制限

クラスの変数やメソッドの中には、クラスの外部から利用して欲しくないものもあるかもしれません。また、クラスを利用する側から見てもクラスの内部で使われているだけで、使う人に関係のないものは見えない方が、間違って使ったり、使い方に迷ったりしにくいです。

そこで、Pythonでは、クラス外部から簡単にはアクセスできないようにすることができます(Javaなどのように完全に制限することはできません)。

この機能を使うには「__(アンダースコア2つ)」を変数名やメソッド名の前につけます

 

書式

class クラス名:
    __クラス変数
    
    def __init__(self):
        self.__インスタンス変数 = 値
        ・・・
        
    def __インスタンスメソッド名():
        ・・・
        
    @classmethod
    def __クラスメソッド名():
        ・・・
        
    @staticmethod
    def __スタティックメソッド名():
        ・・・
    

 

サンプルコード

class MyClass:
    def __init__(self):
        self.__private2 = 5.5
    
    def plus(self, x):
        self.__private2 += x
        self.__show()

    def __show(self):
        print(self.__private2)

test = MyClass()
test.plus(10)
test.__show()

 

実行結果

15.5
Traceback (most recent call last):
  File "/Users/hiroyuki-narita/Desktop/MyDocs/Python3/moduleTest.py", line 14, in 
    test.__show()
AttributeError: 'MyClass' object has no attribute '__show'

 

実行結果を見るとわかるように、クラスの外側からは「__show」が存在しないように見えています。そのため、「__show」を使うことができません。しかし、インスタンスメソッドの中、つまり、クラス定義の中では通常通り「__show」を使うことができます。これがアクセス制限です(ただし、実は特殊な書き方をすることで、__showをクラスの外側から呼び出すことができてしまいます)。

 

また、変数名やメソッド名の頭に「_(アンダースコア1つ)」をつけると、暗黙のルールで「クラスの外側では勝手に使わないでね」という意味になります。これはPythonの機能上の話ではなく、あくまでプログラマの間の紳士協定のようなものです。