Pythonクラスの定義と属性と方法の説明

5871 ワード

クラスベース
クラスステップ
 
Pythonのクラスは、オブジェクト向けプログラミングのすべての基本機能を提供しています.
  • Objectクラスはすべてのクラスの親です(明確に指定する必要はありません).
  • クラスは、複数のベースクラスを継承することを許可する(カンマで分割する).
  • 派生クラスは、ベースクラス内の任意の方法を上書きすることができる.

  • クラスベース
    クラスは2つの操作をサポートします.
  • インスタンス化:inst = clsName(…);
  • 属性参照:インスタンスオブジェクトまたはクラス(クラス属性)を使用してオブジェクトを参照します.

  • クラス定義
    クラスはclassによって定義され、属性と方法が含まれています.
    class ClassName:
        
    
        def funs(self, arg):
            # self is the instance of class
            
    
        @classmethod
        def clsFuns(cls, arg):
            # cls is the class
            
    
        @staticmethod
        def staticFun(arg):
            #        
            
    

    クラス継承
    Pythonはマルチ継承をサポートし、複数の親クラス間をカンマで分割します.親に同じメソッド名があり、子の使用時に指定されていない場合、Pythonは親にメソッドが含まれているかどうかを左から右に順に検索します(つまり、前の親のメソッドを優先的に使用します).
    多重継承(特に菱形継承がある場合)では、検索関係はより複雑になります.具体的には、MRO(Method Resolution Order)によって方法呼び出しの二義的な問題を解決する.MROはまた,C 3アルゴリズム(トポロジーソート+深さ優先探索:入度0のノードを順次取り出し,ノードを取り出した後に関連するエッジを取り除き,再帰処理)を用いて順序を処理する.
    サブクラスでベースクラスの同じ名前のメソッドを呼び出すには、baseCls.funまたはsuper().funが必要です.
    class DerivedClassName(Base1, Base2, Base3):
        
        .
        
    

    変数とアクセス性
    変数(属性)分類:
  • クラス変数:クラスに直接定義され、すべてのクラスオブジェクトに共有されます.クラス名でclsName.varにアクセスします.
  • インスタンス変数:各インスタンス固有のデータ(__init__メソッドで定義、初期化);インスタンスオブジェクトを介してinst.varにアクセスする.

  • Pythonのアクセス性は、約束によって実現されます.
  • プライベート属性:2つの下線で開始され、__var.
  • 保護プロパティ:下線で始まり、_var.自分とサブクラスしかアクセスできません.
  • 一般プロパティ:アルファベットなどで始まります.

  • クラス独自の方法
    Pythonでは、独自の方法を約束することでクラスの機能を強化します.
  • __init__:オブジェクトの生成時に呼び出される関数を構築します(インスタンス変数もこの関数で定義されます).
  • __del__:構造関数、オブジェクトを解放するときに使用します.
  • __repr__:印刷(__str__があればstrを先に試し)、変換;
  • __setitem__:インデックスに従って値を割り当てます.
  • __getitem__:インデックスに従って値を取ります.
  • __len__:長さを取得し、内蔵関数len()を使用する.
  • __cmp__:比較演算;
  • __call__:関数呼び出し(オブジェクトは演算子とみなされる);
  • __add__:加算演算;
  • __sub__:減算演算;
  • __mul__:乗算;
  • __div__:除算;
  • __mod__:余剰演算を求める;
  • __pow__:乗方演算;

  • reprとstr:repr()とstr()は内蔵関数であり、対応するクラスの__repr____str__は文字列を処理する.
  • reprはPython(プログラマー)に友好的で、生成された文字列はeval()を通じてオブジェクトを再構築することができる.
  • strはユーザーに友好的で、ユーザーの理解を便利にする出力である.
  • printの場合は__str__を表示し、定義されていない場合は__repr__を表示します.

  • クラスステップ
    クラスメソッド
    Pythonクラスには、次の3つの方法があります.
  • 一般的な方法:インスタンスメソッドを定義し、最初のパラメータはインスタンスを表す(一般的にselfと表記される).
  • @classmethod修飾方式:クラスメソッドを定義し、最初のパラメータはクラスを表す(一般的にclsと約束されている);
  • @staticmethod修飾方式:静的メソッドを定義する;

  • 次の3つの関数の定義と呼び出し方法を示します.
    class MethodTest:
        index = 0
    
        def __init__(self):
            self.index = -1
    
        def instFun(self, index):
            print('instance function:', index, self.index, MethodTest.index)
            self.index = index
    
        @classmethod
        def classFun(cls, index):
            print('class function:', index, cls.index)
            cls.index = index
    
        @staticmethod
        def staticFun(index):
            print('static function:', index, MethodTest.index)
    
    
    if __name__=="__main__":
        mtest = MethodTest()
        mtest.instFun(1)  # instance function: -1 0
        mtest.classFun(2)  # class function: 0 0
        mtest.staticFun(3)  # static function: 3 2
        MethodTest.classFun(4)  # class function: 2 2
        MethodTest.instFun(mtest, 5)  # instance function: 1 4
        MethodTest.staticFun(6)  # static function: 6 4
    

    インスタンスオブジェクトによって3つのメソッドを直接呼び出すことができます.クラス名を使用すると、静的メソッドとクラスメソッドを直接呼び出すことができます.インスタンスメソッドを呼び出すには、インスタンスオブジェクトを渡す必要があります.
    クラス属性get/setプロパティにより、変数の制御を強化し、後続の変更と拡張を容易にすることができます.ただし、クラス内の属性(get/set)メソッドは手動で実装するのではなく、@properyを使用して実装を修飾する必要があります.
  • は1つのget方法を属性に変え、@properyの修飾を増やすだけでよい.
  • @propery自体はまた別の装飾器を作成し、1つのsetterメソッドを属性付与に変更します.setterメソッドを追加しないと、属性は読み取り専用になります.

  • 次は属性定義の例です.countのget属性を@properyで定義し、@count.setterでset属性を定義できます.
    class CountProp:
        def __init__(self):
            self._count=0
    
        @property
        def count(self):
            return self._count
    
        @count.setter
        def count(self, newCount):
            self._count = newCount
    
        def __getattr__(self, name):
            print('call __getattr__:', name)
            value = '{} value for {}'.format(self._index, name)
            self._index += 1
            setattr(self, name, value)
            return value
    
        def __getattribute__(self, name):
            print('call __getattribute__:', name)
            try:
                return super().__getattribute__(name)
            except AttributeError:
                # setattr(self, name, value)
                raise
    
    cPro = CountProp()
    print(cPro.count)    # 0
    cPro.count = 10
    print(cPro.count)    # 10    
    
        
    

    クラス内のプロパティは、クラス定義(または初期化時)定義のほか、いつでもバインドできます(存在しないプロパティに値を割り当てると自動的にバインドされます).属性の取得と付与のルールは次のとおりです.
  • は、まずgetattributeを呼び出します.属性が存在するかどうかにかかわらず(属性が存在しない場合はAttributeError異常を放出する必要があります)、このメソッド内で属性を参照することはできません.そうしないと、ループ再帰を引き起こします.したがって、属性にアクセスするにはsuper()を呼び出す.XXXは再帰を避ける.
  • 属性が存在しない場合(オブジェクトのインスタンス辞書で属性がクエリーされない場合)、クラスがgetattrを定義している場合、このメソッドが呼び出されます.
  • プロパティに値を割り当てるかsetattr関数を呼び出すと、setattrメソッドがトリガーされます.