Python3.5ノート——第8章オブジェクト向けプログラミング

16318 ワード

Python3.5ノート


第8章オブジェクト向けプログラミング


オブジェクト向け用語の説明

  • クラス:同じプロパティとメソッドを持つオブジェクトのセットを記述します.クラス定義には、各オブジェクトに共通するプロパティとメソッドが集合します.オブジェクトはクラスの例です.
  • クラス変数(属性):クラス属性はインスタンス化されたオブジェクト全体で共通です.クラス変数はクラスに定義され、メソッドの外にあります.クラスのハイライトは通常、適量の変数として使用されません.クラス変数は属性とも呼ばれます.
  • データ・メンバー:クラス変数またはインスタンス変数は、クラスおよびそのインスタンス変数に関するデータを処理するために使用されます.
  • メソッド書き換え:親クラスから継承されたメソッドが、子クラスのニーズを満たすことができない場合は、メソッドの上書きと呼ばれ、メソッドの書き換えとも呼ばれます.
  • インスタンス変数:現在のインスタンスのクラスにのみ使用されるメソッド内の変数を定義します.
  • マルチステート:異なるオブジェクトに対して同じ操作を使用します.
  • カプセル化:外部オブジェクトの作業の詳細を非表示にします.
  • 継承:派生クラスがベースクラスを継承するフィールドとメソッドです.継承により、派生クラスのオブジェクトをベースクラスオブジェクトとして扱い、通常のクラスに基づいて専門的なクラスオブジェクトを構築できます.
  • インスタンス化:クラスのインスタンス、クラスの特定のオブジェクトを作成します.
  • メソッド:クラスで定義された関数.
  • オブジェクト:クラスによって定義されたデータ構造のインスタンス.オブジェクトには、2つのデータ・メンバー(クラス変数とインスタンス変数)とメソッドが含まれます.

  • クラスの定義


    例:
    #! /usr/bin/python3
    # -*- coding:UTF-8 -*-
    class MyClass(object):
        i = ' '
        def f(self):
            return 'hello world %s' % self.i
    

    クラス定義の書き方:
  • classキーワードを使用します.classキーワードの後ろにはクラス名が付いています.クラス名は通常、頭文字が
  • です.
  • クラス名の後に続くのは(object)で、そのクラスがどのクラスから継承されたかを示し、適切な継承クラスがなければobjectクラスを使用します.これはすべてのクラスが最終的に継承されるクラスです.
  • クラスには、通常、プロパティとメソッドが含まれます.クラスでメソッドを定義する場合は、最初のパラメータはselfでなければなりません.最初のパラメータを除いて、クラスのメソッドは通常の関数と何の違いもありません.

  • クラスの使用

    #! /usr/bin/python3
    # -*- coding:UTF-8 -*-
    class MyClass(object):
        i = ' '
        def f(self):
            return 'hello world %s' % self.i
    
    my_class = MyClass()
    print(' :',my_class.i)
    print(' :',my_class.f())
    

    出力:
     :  
     : hello world  
    

    クラスの使用は、関数呼び出しよりも多くの操作を行います.
  • my_class=MyClass()このステップをクラスのインスタンス化と呼び、クラスのインスタンスを作成します.ここから得たmy_class変数はクラスの特定のオブジェクトと呼ばれます.
  • クラスで定義されたメソッドを呼び出します.selfが渡さない以外は、他のパラメータが正常に入力されます.
  • クラス属性参照の構文はobj.name,objはクラスオブジェクトであり,nameは属性を表す.

  • クラスの構築方法


    Pythonでは、Init()メソッドは、オブジェクトのインスタンス化時に呼び出される特殊なメソッドです.この方法の書き方は、まず2つの下線を入力し、その後initを入力し、次に2つの下線を入力します.この方法は構造方法とも呼ばれます.クラスを定義するときに表示されない定義_Init()メソッドでは、デフォルトでは、パラメータのない構築メソッドが呼び出されます.例は次のとおりです.
    class MyClass2(object):
        i = 123
        def __init__(self,name1,age1):
            self.name = name1
            self.age = age1
    
        def f(self):
            return 'hello %s,you are %s years old!' % (self.name,self.age)
    
    my_class2 = MyClass2(' ','23')
    print(' :',my_class2.name)
    print(' :',my_class2.age)
    print(' :',my_class2.f())
    

    出力:
     :  
     : 23
     : hello  ,you are 23 years old!
    

    1つのクラスでは複数の構造メソッドを定義できますが、クラスをインスタンス化する場合は最後の構造メソッドのみをインスタンス化します.すなわち、後の構造メソッドは前の構造メソッドを上書きし、最後の構造メソッドのパラメータに基づいてインスタンス化する必要があります.1つのクラスで、1つの構築方法のみを定義することをお勧めします.

    クラスのアクセス権


    パブリック属性とメソッドへの直接アクセス


    クラスの内部には属性とメソッドがあり、外部コードは属性とメソッドを直接呼び出すことができます.例は次のとおりです.
    #! /user/bin/python3
    # -*- coding:UTF-8 -*-
    class Student(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def info(self):
            print('hello %s,you are %s years old!' % (self.name,self.age))
    
    stu = Student(' ','23')
    stu.info()
    stu.name = ' '
    stu.age = '24'
    stu.info()
    

    出力:
    hello  ,you are 23 years old!
    hello  ,you are 24 years old!
    

    プライベート属性の定義とアクセス方法


    クラスの内部プロパティが外部からアクセスされないようにするには、プロパティ名の前に下線_を2つ追加します.Pythonでは、インスタンスの変数名が2つの下線で始まると、プライベート変数になり、内部のみアクセスでき、外部はアクセスできません.この場合、直接アクセスするとエラーが発生します.例は次のとおりです.
    #! /user/bin/python3
    # -*- coding:UTF-8 -*-
    class Student(object):
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print('hello %s,you are %s years old!' % (self.__name, self.__age))
    
    stu = Student(' ','23')
    stu.info()
    stu.__name = ' '
    stu.__age = '24
    stu.info()
    

    出力:
    Traceback (most recent call last):
      File "D:/pyspace/hellopython/Chapter8.py", line 60, in 
        stu.info()
      File "D:/pyspace/hellopython/Chapter8.py", line 57, in info
        print('hello %s,you are %s years old!' % (self.name,self.age))
    AttributeError: 'Student' object has no attribute 'name'
    

    この場合、クラスにget_を追加することでattrs()メソッドで、クラス内のプライベート変数を取得します.クラスにset_を追加できますattrs()メソッドで、クラス内のプライベート変数を変更します.例は次のとおりです.
    class Student(object):
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print('hello %s,you are %s years old!' % (self.__name,self.__age))
    
        def get_name(self):
            return self.__name
    
        def set_name(self,name):
            self.__name = name
    
        def get_age(self):
            return self.__age
    
        def set_age(self,age):
            self.__age = age
    stu = Student(' ','23')
    stu.info()
    stu.set_name(' ')
    print(' :',stu.get_name())
    stu.set_age('24')
    print(' ',stu.get_age())
    

    出力:
    hello  ,you are 23 years old!
     :  
      24
    

    プライベートメソッドの定義とアクセス方法


    メソッド名に下線を2つ付けることで、メソッドをプライベートメソッドとして定義できます.プライベートメソッドは外部コードから直接アクセスできず、クラス内で共通メソッドでのみ呼び出されます.例は次のとおりです.
    #! /user/bin/python3
    # -*- coding:UTF-8 -*-
    class Student(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __info(self):
            print('hello %s,you are %s years old!' % (self.name,self.age))
    
        def foo(self):
            self.__info()
    
    stu = Student(' ','23')
    stu.foo()
    

    出力:
    hello  ,you are 23 years old!
    

    継承


    classを定義すると、既存のclassから継承できます.定義された新しいclassはサブクラス(SubClass)と呼ばれ、継承されたclassはベースクラス、親クラス、またはスーパークラス(BaseClass、Super Class)と呼ばれます.継承されたフォーマットは次のとおりです.
    class DerivedClassName(BaseClassName):
        statemnt-1
        ...
        statement-n
    

    構文classサブクラス名(ベースクラス名)を継承する場合、ベースクラス名はカッコ内に書き込まれ、メタグループに指定されます.特徴は以下の通りである.
  • 継承では、ベースクラスの構造メソッドは自動的に呼び出されず、サブクラスの構造メソッドで特別に呼び出される必要がある.
  • ベースクラスのメソッドを呼び出す場合は、ベースクラスのクラス名接頭辞を付け、selfパラメータ変数を付ける必要があります.クラスで通常のメソッドを呼び出す場合とは異なりselfパラメータは必要ありません.
  • Pythonでは、まず対応するタイプのメソッドを検索し、サブクラスで対応するメソッドが見つからない場合は、ベースクラスごとに検索します.
  • class Animal(object):
        def run(self):
            print('animal is running....')
    
    class Dog(Animal):
        pass
    
    class Cat(Animal):
        pass
    
    dog = Dog()
    dog.run()
    cat = Cat()
    cat.run()
    

    出力:
    animal is running....
    animal is running....
    

    子クラスは、親のプライベートメソッドを継承することも、親のプライベートメソッドを呼び出すこともできません.

    マルチステート


    子クラスと親クラスが同じメソッドを持つ場合、子クラスのメソッドは親クラスのメソッドを上書きし、メソッド呼び出し時に常に子クラスのメソッドを最初に呼び出します.これがマルチステートです.例は次のとおりです.
    #! /user/bin/python3
    # -*- coding:UTF-8 -*-
    class Animal(object):
        def run(self):
            print('animal is running....')
    
    class Dog(Animal):
        def run(self):
            print('dog is running....')
    
    class Cat(Animal):
        def run(self):
            print('cat is running...')
    
    dog = Dog()
    dog.run()
    cat = Cat()
    cat.run()
    print('dog animal ',isinstance(dog,Animal))
    print('dog dog ',isinstance(dog,Animal))
    

    出力:
    dog is running....
    cat is running...
    dog animal  True
    dog dog  True
    

    例えば、上記の例では、dogとcatはそれぞれanimalを継承し、それぞれ独自のrunメソッドを定義し、最後にそれぞれのrunメソッドを呼び出す.
    マルチステートを使用する利点は、Dog、Catなどのサブクラスオブジェクトを入力する必要がある場合、親のAnimalオブジェクトを受信するだけでよいことです.Dog、CatなどはAnimalタイプなので、Animalタイプに従ってパラメータを入力すればよいからです.Animalタイプにはrun()メソッドがあるため、入力されるタイプはAnimalクラスまたはAnimalのサブクラスであれば、インスタンスタイプのメソッドが自動的に呼び出されます.

    多重継承


    前節では単一継承について述べ,Pythonは多重継承もサポートしている.多重継承クラスは次のように定義されます.
    class DerivedClassName(Base1,Base2,Base3):
        statment-1
        ...
        statement-n
    

    多重継承は、複数のベースクラス(親またはスーパークラス)があることがわかります.
    カッコ内の親の順序に注意してください.親に同じメソッド名がある場合、子の使用時に指定されていない場合、Pythonは左から右に検索されます.メソッドが子クラスに見つからない場合は、親クラスにこのメソッドが含まれているかどうかを左から右に検索します.

    オブジェクト情報の取得


    type()関数の使用


    判断基本タイプはtype()関数で判断できます.次のようになります.
    print('-----------type() -----------')
    print(type('abc'))
    print(type(123))
    print(type(None))
    print(type(abs))
    
    print(type('abc')==str)
    print(type(123)==int)
    
    print('----------- -----------')
    import types
    def func():
        pass
    
    print(type(func)==types.FunctionType)
    print(type(abs)==types.BuiltinFunctionType)
    print(type(lambda x,y,z:x+y+z)==types.LambdaType)
    print(type(x for x in range(1,10))==types.GeneratorType)
    

    出力:
    -----------type() -----------
    
    
    
    
    True
    True
    ----------- -----------
    True
    True
    True
    True
    

    isinstance()関数の使用


    isinstance()関数を使用すると、オブジェクトが何らかのタイプであるかどうかを教えてくれます.
    print('dog animal ',isinstance(dog,Animal))
    print('dog dog ',isinstance(dog,Animal))
    

    しゅつりょく
    dog animal  True
    dog dog  True
    

    dir()関数の使用


    オブジェクトのすべてのプロパティとメソッドを取得するにはdir()関数を使用します.dir()関数は、文字列のlistを返します.次のようになります.
    print(dir('abc'))
    

    出力:
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
    

    クラスの独自の方法


    _str_


    Javaのto_に相当string()メソッド.次のようになります.
    class Student(object):
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def __str__(self):
            return ' :%s, :%s' % (self.__name,self.__age)
    
    print(Student(' ','23'))
    stu_abc = Student(' ','24')
    print(stu_abc)
    

    出力:
     : , :23
     : , :24
    

    注意:str_メソッドは文字列を返さなければなりません

    _iter_


    クラスをforに使用する場合は...inループはlistやtupleのように1つの_を実現しなければならない.iter_()メソッド.このメソッドは反復オブジェクトを返します.Pythonのforループは反復オブジェクトを呼び出し続けます.next()メソッドは、StopIterationエラーが発生したときにループを終了するまで、ループの次の値を取得します.次のようになります.
    class Fib(object):
        def __init__(self):
            self.a, self.b = 0, 1 #  a、b
    
        def __iter__(self):
            return self #  , 
    
        def __next__(self):
            self.a, self.b = self.b, self.a + self.b #  
            if self.a > 100000: #  
                raise StopIteration();
            return self.a #  
    
    for n in Fib():
        print(n)
    

    出力:
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987
    1597
    2584
    4181
    6765
    10946
    17711
    28657
    46368
    75025
    

    _getitem()_


    リストのように下付き文字で要素を取り出すには、_getitem()_メソッドの例は次のとおりです.
    class Fib(object):
        def __getitem__(self, n):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        
    print(Fib()[3])
    

    出力:
    3
    

    _getattr_


    使用_getattr_メソッドはプロパティを動的に返します.次のようになります.
    class Student1(object):
    
        def __getattr__(self, attr):
            if attr == 'score':
                return 95
    
    
    stu1 = Student1()
    print(stu1.score)
    

    出力:
    95
    

    _call_


    クラス定義を指定します.callメソッドでは、インスタンスを直接呼び出して結果を得ることができます._callはパラメータを定義することもできます.インスタンスを直接呼び出すと、1つの関数を呼び出すように、オブジェクトを関数と見なし、関数をオブジェクトと見なすことができます.この二つにはもともと根本的な違いはないからだ.オブジェクトを関数と見なすと、クラスのインスタンスが実行中に作成されるため、関数自体が実行中に動的に作成されます.これにより,オブジェクトと関数の境界がぼやけてしまう.例は次のとおりです.
    #! /usr/bin/python3
    # -*- coding:UTF-8 -*-
    class Student(object):
        def __init__(self,name):
            self.name = name
    
        def __call__(self, *args, **kwargs):
            print(' :%s' % self.name)
    
    stu2 = Student(' ')
    stu2()
    

    出力:

    Callable()関数を使用して、オブジェクトが呼び出されるかどうかを判断できます.例は次のとおりです.
    print(callable(Student(' ')))
    print(callable(Student1()))
    print(callable(max))
    print(callable([1,2,3]))
    

    出力:
    True
    False
    True
    False
    

    牛刀小试--旅の提案


    サトシは今日出かけたいのですが、今日の天気が外出に適しているかどうかは分かりません.彼にアドバイスを提供するプログラムが必要です.プログラムのアドバイスはdaytimeとnightを入力し、視認度と温度によって移動のアドバイスと使用の交通手段を提供し、需要の変更の可能性を考慮する必要があります.
    需要分析:本章で学んだパッケージ、継承、マルチステートを使用すると実現しやすく、親パッケージから可視度と温度を表示する方法で、子が親を継承します.必要に応じて、子クラスは親クラスのメソッドを上書きし、独自の実装を行うことができます.サブクラスはメソッドをカスタマイズすることもできます.
    class WeatherSeach(object):
        def __init__(self,input_daytime):
            self.input_daytime = input_daytime
    
        def search_visible(self):
            visible = 0
            if self.input_daytime == 'daytime':
                visible = 6
            elif self.input_daytime == 'night':
                visible = 2
            return visible
    
        def search_temperature(self):
            temperature = 0
            if self.input_daytime == 'night':
                temperature = 16
            elif self.input_daytime == 'daytiem':
                temperature = 26
    
            return temperature
    
    class OutAdvice(WeatherSeach):
        def __init__(self,input_daytime):
            WeatherSeach.__init__(self,input_daytime)
    
        def search_temperature(self):
            we_use = 'none'
            if self.input_daytime == 'daytime':
                we_use = ' '
            elif self.input_daytime == 'night':
                we_use = ' '
            return we_use
    
        def take_advice(self):
            we_use = self.search_temperature()
            visible = self.search_visible()
            if visible >= 6:
                print(' , %s ' % we_use)
            elif 0 < visible <= 2:
                print(' , %s ' % we_use)
            else:
                print(' , !')
    
    oa = OutAdvice('night')
    oa.take_advice()
    

    しゅつりょく

    質問の回答


    二重下線の先頭のインスタンス変数は必ず外部からアクセスできませんか?


    答え:いいえ、直接アクセスできないのはPython解釈器が外部にscore変数が_になりましたStudent__scoreですので、Student_scoreアクセス変数_score.次のようになります.
    class Student(object):
        def __init__(self,name,score):
            self.__name = name
            self.__socre = score
    
        def info(self):
            print(' :%s, :%s' % (self.__name,self.__socre))
    
        def get_score(self):
            return self.__socre
    
    stu3 = Student(' ','94')
    stu3.info()
    #print(' :',stu3._Student__score) # 
    print(' :',stu3.get_score())
    

    出力:
     : , :94
     : 94
    

    メソッドと関数の違い


    答え:Pythonでは、関数はクラスに依存せず、クラスで定義されていません.メソッドはクラスに依存し、クラスで定義され、本質的には関数です.区別を容易にするために,クラス内の関数をメソッドと呼び,クラスに依存しない関数を関数と呼ぶ.

    クラスを使用する理由


    Pythonでは、継承、カプセル化、多態の3つの特性を借りて、クラスを使用して1つの実物をよりよく管理することができ、同じ機能と行為を持つ物事を1つのクラスにカプセル化することができ、他の同じ特性を持つものは直接クラスを継承することができ、親のカプセル化の良い方法を得ることができます.同時に、サブクラスは親のメソッドを上書きして、特定の機能要件を満たすことができ、サブクラスは自分の機能を拡張することができます.クラスを使用すると、コードの多重化と拡張がよりよく実現されます.