週末!プログラミング部

ソフトウェア開発ネタを中心に自分でいろいろ調べた内容を自分の勝手な解釈で思うがままに書いくためのブログ。サンプルソースコード、API、プラットフォーム、プログラミング言語、開発環境などを調査、分析して追求いく予定です。

Pythonにおけるクラスの使い方とスコープを確認してみる

会社の若い子たちがPhysonで機械学習とかやっているようなので自分も勉強してみることにしました。
基本的な文法はなんとなくわかる気がするので、Pythonにおけるクラスの使い方とスコープから初めてみたいと思います。
自分のお勉強目的の備忘録なのでわかりにくい表現を使うかもしれませんがお許し下さいm(T▽T)m

スコープ確認用のクラス

今回は動作確認用に以下のクラスを準備しました。

# coding: utf-8

class testClass :

    # publicなクラス変数
    class_variable_A = 1

    # privateなクラス変数
    __class_variable_B = 2

    # コンストラクタ
    def __init__(self) :
        print( "コンストラクタを呼び出し" )
        
        # publicなインスタンス変数
        self.instance_variable_A = 3
        
        # privateなインスタンス変数
        self.__instance_variable_B = 4

    # デストラクタ
    def __del__(self) :
        print( "デストラクタを呼び出し" )

    # publicなクラスメソッド
    @classmethod
    def class_method_A(cls) :
        print( "publicなクラスメソッドを呼び出し" )

    # privateなクラスメソッド
    @classmethod
    def __class_method_B(cls) :
        print( "privateなクラスメソッドを呼び出し" )

    # publicなインタンスメソッド
    def instance_method_A(self) :
        print( "publicなインタンスメソッド" )

    # privateなインタンスメソッド
    def __instance_method_B(self) :
        print( "privateなインタンスメソッド" )


コンストラク

インスタンスが作成されるタイミングで呼び出されるメソッドです。
書き方は以下のとおり。「__init__」という関数を定義する感じです。
引数のselfは、インスタンス自身を示す特殊な引数。JavaC#でいうthis句みたいなもの。
なお、ここではselfという変数名にしていますが別にselfとする必要はありません。
ただ伝統的にselfが使われるようなので従っておきます。

def __init__(self) :

なおクラスからインスタンスを作成するには以下のような感じです。
JavaC#のようにnew句は必要ないようです。
またself変数も指定する必要はありません。
※以降の説明ではobjという変数はtestClassクラスのインスタンスを指します。

obj = testClass()


デストラク

インスタンスが破棄されるタイミングで呼び出されるメソッドです。
書き方は以下のとおり。「__del__」という関数を定義する感じです。
selfはコンストラクタと同じです。

def __del__(self) :


publicなクラス変数

javaC#でいうpublic staticなフィールド変数みたいなもののようです。
宣言はclass内で普通に変数宣言すればよいようです。
「クラス名.変数名」でアクセス可能です。

print("class_variable_A =", testClass.class_variable_A)

また、インスタンス名.変数名でもアクセス可能です。

print("class_variable_A =", obj.class_variable_A)


privateなクラス変数

javaC#でいうprivate staticなフィールド変数みたいなもののようです。
宣言はpublicなクラス変数と同様ですが、変数名の前に__を付ける必要があります。
privateとしていますが「クラス名._クラス名__変数名」でアクセスができてしまいます。

print("__class_variable_B =", testClass._testClass__class_variable_B)

また、「インスタンス名._クラス名__変数名」でもアクセス可能です。

print("__class_variable_B =", obj._testClass__class_variable_B)


publicなインスタンス変数

javaC#でいうpublic なフィールド変数のようです。
コンストラクタやインスタンスメソッドの引数であるselfを使って、「self.変数名」で宣言可能です。
インスタンス名.変数名」でアクセス可能です。

print("instance_variable_A =", obj.instance_variable_A) 


privateなインスタンス変数

javaC#でいうprivateなフィールド変数のようです。
コンストラクタやインスタンスメソッドの引数であるselfを使って、「self.__変数名」で宣言可能です。
privateとしていますが「インスタンス名._クラス名__変数名」でアクセスができてしまいます。

print("__instance_variable_B =", obj._testClass__instance_variable_B)


publicなクラスメソッド

javaC#でいうpublic staticなメソッドみたいなものです。
宣言はクラス内で関数宣言した後に@classmethodというアノテーションを付けます。
引数clsはクラス自身を示す特殊な引数です。

@classmethod
def class_method_A(cls) :

「クラス名.メソッド名」でアクセス可能です。

testClass.class_method_A()  

また、インスタンス名.メソッド名でもアクセス可能です。

obj.class_method_A()  


privateなクラスメソッド

javaC#でいうprivate staticなメソッドみたいなもののようです。
宣言はpublicなクラス変数と同様ですが、メソッド名の前に__を付ける必要があります。
privateとしていますが「クラス名._クラス名__メソッド名」でアクセスができてしまいます。

testClass._testClass__class_method_B()

また、「インスタンス名._クラス名__メソッド名」でもアクセス可能です。

obj._testClass__class_method_B()


publicなインスタンスメソッド

javaC#でいうpublicなメソッドのようです。
宣言はクラス内で関数宣言します。引数にはコンストラクタ同様にselfを持ちます。
インスタンス名.変数名」でアクセス可能です。

obj.instance_method_A() 


privateなインスタンスメソッド

javaC#でいうprivateなメソッドみたいなもののようです。
宣言はpublicなインスタンスメソッドと同様ですが、メソッド名の前に__を付ける必要があります。
privateとしていますが「インスタンス名._クラス名__メソッド名」でアクセスができてしまいます。

obj._testClass__instance_method_B()


動作確認

動作確認用に以下のプログラムを用意しました。

# coding: utf-8

from test import testClass

# インスタンス化
obj = testClass()

# publicなクラス変数にアクセス
print("class_variable_A =", testClass.class_variable_A)               # クラスからアクセス
print("class_variable_A =", obj.class_variable_A)                     # インスタンスからアクセス

# privateなクラス変数にアクセス
#print("__class_variable_B =", testClass.__class_variable_B)          # クラスからアクセス:エラー
print("__class_variable_B =", testClass._testClass__class_variable_B) # クラスからアクセス
#print("__class_variable_B =", obj.__class_variable_B)                # インスタンスからアクセス:エラー
print("__class_variable_B =", obj._testClass__class_variable_B)       # インスタンスからアクセス

# publicなインスタンス変数にアクセス
print("instance_variable_A =", obj.instance_variable_A)               # インスタンスからアクセス

# privateなインスタンス変数にアクセス
#print("__instance_variable_B =", obj.__instance_variable_B)          # インスタンスからアクセス:エラー
print("__instance_variable_B =", obj._testClass__instance_variable_B) # インスタンスからアクセス

# publicなクラスメソッドを呼び出し
testClass.class_method_A()                                            # クラスからアクセス
obj.class_method_A()                                                  # インスタンスからアクセス

#privateなクラスメソッドを呼び出し
#testClass.__class_method_B()                                         # クラスからアクセス:エラー
testClass._testClass__class_method_B()                                # クラスからアクセス
#obj.__class_method_B()                                               # クラスからアクセス:エラー
obj._testClass__class_method_B()                                      # クラスからアクセス

# publicなインスタンスメソッドを呼び出し
obj.instance_method_A()                                               # インスタンスからアクセス

# privateなインスタンスメソッドを呼び出し
#obj.__instance_method_B()                                            # インスタンスからアクセス:エラー
obj._testClass__instance_method_B()                                   # インスタンスからアクセス


実行結果は以下になります。

コンストラクタを呼び出し
class_variable_A = 1
class_variable_A = 1
__class_variable_B = 2
__class_variable_B = 2
instance_variable_A = 3
__instance_variable_B = 4
publicなクラスメソッドを呼び出し
publicなクラスメソッドを呼び出し
privateなクラスメソッドを呼び出し
privateなクラスメソッドを呼び出し
publicなインタンスメソッド
privateなインタンスメソッド
デストラクタを呼び出し