Python学習ノート10:対象に向かってステップアップして終了

10322 ワード

1. __slots__変数#ヘンスウ#
  • Pythonは動的言語であるため、通常、動的言語はプログラムの実行時に使用できます.
  • オブジェクトに新しい属性またはメソッド
  • をバインドする
  • はまた、バインドされた属性および方法のバインド解除
  • を行うことができる.
  • カスタムタイプのオブジェクトを特定する必要がある場合は、クラスで__を定義することで、特定のプロパティのみをバインドできます.slots__変数を定義します.
  • 注意:_slots__の定義は、現在のクラスのオブジェクトにのみ有効であり、サブクラスには何の役にも立たない.

  • class Student(object):
        
        #  tuple           
        #   Student       name age  
        __slots__ = ('name', 'age')  
    
    
    class GraduateStudent(Student):
        pass
    
    
    s = Student()  #       
    s.name = 'Jackson'  #     'name'
    s.age = 20  #     'age'
    
    # s.score = 100
    # ERROR: AttributeError: 'Student' object has no attribute 'score'
    
    
    # slots             ,          :
    g = GraduateStudent()
    g.score = 100
    print('g.score =', g.score)		 # g.score = 100
    
    

    2.静的メソッドとクラスメソッド
  • 以前、クラスで定義されたメソッドはすべてオブジェクトメソッドであり、すなわち、これらのメソッドはすべてオブジェクトに送信されるメッセージであった.
  • 実際には、クラスに書く方法はすべてオブジェクトメソッドである必要はありません.たとえば、次のようにします.
  • 「三角形」クラスを定義し、3つの辺長を伝達することによって三角形を構築し、周長と面積を計算する方法
  • を提供する.
  • しかし、入力された3つの辺長は必ずしも三角形オブジェクトを構築できるとは限らないので、まず3つの辺長が三角形を構成できるかどうかを検証する方法を書くことができます.この方法は、この方法を呼び出すときに三角形オブジェクトがまだ作成されていないため(3つの辺が三角形を構成できるかどうか分からないため)
  • ではありません.
  • であるため、この方法は三角形クラスに属するが、三角形オブジェクトに属さない
  • である.
  • 静的手法を用いてこのような問題を解決することができる:
  • from math import sqrt
    
    
    class Triangle(object):
    
        def __init__(self, a, b, c):
            self._a = a
            self._b = b
            self._c = c
        
        #       
        @staticmethod
        def is_valid(a, b, c):
            return a + b > c and b + c > a and a + c > b
    
        def perimeter(self):
            return self._a + self._b + self._c
    
        def area(self):
            half = self.perimeter() / 2
            return sqrt(half * (half - self._a) *
                        (half - self._b) * (half - self._c))
    
    
    def main():
        a, b, c = 3, 4, 5
        #                      
        if Triangle.is_valid(a, b, c):
            t = Triangle(a, b, c)
            print(t.perimeter())
            #                                  
            # print(Triangle.perimeter(t))
            print(t.area())
            # print(Triangle.area(t))
        else:
            print('       .')
    
    
    if __name__ == '__main__':
        main()
        # 12
        # 6.0
    
    
  • は静的メソッドと比較的類似しており、Pythonはクラス内でクラスメソッドを定義することもできます.
  • クラスメソッドの最初のパラメータ規則名はcls
  • である.
  • 現在のクラスに関する情報のオブジェクト(クラス自体もオブジェクトであり、クラスのメタデータオブジェクトとも呼ばれる場合がある)
  • を表す.
  • このパラメータにより、クラスに関する情報を取得することができ、クラスのオブジェクト
  • を作成することができる.
    from time import time, localtime, sleep
    
    
    class Clock(object):
        """    """
    
        def __init__(self, hour=0, minute=0, second=0):
            self._hour = hour
            self._minute = minute
            self._second = second
    
        #      :
        @classmethod
        def now(cls):
            ctime = localtime(time())
            return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
    
        def run(self):
            """  """
            self._second += 1
            if self._second == 60:
                self._second = 0
                self._minute += 1
                if self._minute == 60:
                    self._minute = 0
                    self._hour += 1
                    if self._hour == 24:
                        self._hour = 0
    
        def show(self):
            """    """
            return '%02d:%02d:%02d' % \
                   (self._hour, self._minute, self._second)
    
    
    def main():
        #                 
        clock = Clock.now()
        while True:
            print(clock.show())
            sleep(1)
            clock.run()
    
    
    if __name__ == '__main__':
        main()
    

    3.クラス間の関係
  • 簡単に言えば、クラスとクラスの関係は3つあります.is-a、has-a、use-aの関係です.
  • s-a関係(継承または汎化)、例えば学生と人の関係、携帯電話と電子製品の関係は継承関係に属する.
  • has-a関係(関連)、例えば部門と従業員の関係、自動車とエンジンの関係は関連関係に属している.
  • 集約関係:関連関係が全体と部分の関連である場合.
  • 合成関係:全体がさらに部分のライフサイクルを担当している場合(全体と部分は分割不可能であり、同時に同时に消滅する)、このような最も強い関連関係である.

  • use-a関係(依存)、例えば運転手が運転する行為(方法)があり、その中で(のパラメータ)が自動車に使用されると、運転手と自動車の関係は依存関係である.

  • UML(統合モデリング言語)を使用してオブジェクト向けモデリングを行うことができます.重要な作業の一つは、クラスとクラスの関係を標準化されたグラフィックシンボルで記述することです.

  • 4.継承とマルチステート
  • 先ほど述べたように、既存のクラスに基づいて新しいクラスを作成することができます.この1つの方法は、あるクラスが別のクラスから属性と方法を直接継承し、重複コードの作成を減らすことです.
  • 継承情報を提供するものを親と呼び、スーパークラスまたはベースクラスとも呼ぶ.
  • 継承情報を得たものをサブクラス、派生クラスまたは派生クラスとも呼ぶ.
  • 子クラスは、親が提供する属性とメソッドを継承するだけでなく、独自の属性とメソッドを定義することもできるので、子クラスは親よりも多くの能力を持つ
  • .
  • リ氏置換の原則:実際の開発では、親オブジェクトをサブクラスオブジェクトで置換することがよくあります.これは、オブジェクト向けプログラミングでよく見られる動作
  • です.
  • リッツ置換原則の内容は、「派生クラス(サブクラス)オブジェクトは、そのベースクラス(スーパークラス)(親)オブジェクトの代わりにプログラム内で置換することができる」と記述することができる.

  • 次に継承の例を見ます:
  • #   :
    class Person(object):
        """ """
    
        def __init__(self, name, age):
            self._name = name
            self._age = age
    
        @property
        def name(self):
            return self._name
    
        @property
        def age(self):
            return self._age
    
        @age.setter
        def age(self, age):
            self._age = age
    
        def play(self):
            print('%s    Python.' % self._name)
    
        def watch_mv(self):
            if self._age >= 18:
                print('%s        .' % self._name)
            else:
                print('%s    《       》 .' % self._name)
    
                
    #      :
    class Student(Person):
        """  """
    
        def __init__(self, name, age, grade):
            super().__init__(name, age)
            self._grade = grade
    
        @property
        def grade(self):
            return self._grade
    
        @grade.setter
        def grade(self, grade):
            self._grade = grade
    
        def study(self, course):
            print('%s %s    %s.' % (self._grade, self._name, course))
    
    
    #      :
    class Teacher(Person):
        """  """
    
        def __init__(self, name, age, title):
            super().__init__(name, age)
            self._title = title
    
        @property
        def title(self):
            return self._title
    
        @title.setter
        def title(self, title):
            self._title = title
    
        def teach(self, course):
            print('%s%s   %s.' % (self._name, self._title, course))
    
    
    def main():
        stu = Student('   ', 15, '  ')
        stu.study('  ')
        stu.watch_mv()
        t = Teacher('   ', 25, ' Boss')
        t.teach('    Python  ')
        t.watch_mv()
    
    
    if __name__ == '__main__':
        main()
        #             .
        #        《       》 .
        #     Boss       Python  .
        #            .
        
    
  • サブクラスは、親のメソッドを継承した後、親の既存のメソッドに新しい実装バージョンを与えることができ、この動作をメソッド書き換え(override)と呼ぶ.
  • メソッド書き換えにより、親の同じ動作をサブクラスで異なる実装バージョンにすることができ、このサブクラス書き換えメソッドを呼び出すと、異なるサブクラスオブジェクトが異なる動作を示すことができます.これがマルチステートです.
  • from abc import ABCMeta, abstractmethod
    
    
    class Pet(object, metaclass=ABCMeta):
        """  """
    
        def __init__(self, nickname):
            self._nickname = nickname
        
        #     
        @abstractmethod
        def make_voice(self):
            """    """
            pass
    
    
    class Dog(Pet):
        """ """
    
        def make_voice(self):
            print('%s:    ...' % self._nickname)
    
    
    class Cat(Pet):
        """ """
    
        def make_voice(self):
            print('%s:  ... ...' % self._nickname)
    
    
    def main():
        pets = [Dog('  '), Cat('  '), Dog('  ')]
        for pet in pets:
            pet.make_voice()
    
    
    if __name__ == '__main__':
        main()
        #   :    ...
        #   :  ... ...
        #   :    ...
        
    
  • のコードでは、Petクラスを抽象クラスに処理しました.
  • 抽象クラスとはオブジェクトを作成できないクラスであり、このクラスの存在は他のクラスに
  • を継承させるためである.
  • Pythonは文法的にJavaやC#のように抽象クラスのサポートを提供していませんが、abcモジュールのABCMetaメタクラスやabstractmethodパッケージを通じて抽象クラスの効果を達成することができます.
  • クラスに抽象メソッドが存在する場合、このクラスはインスタンス化(オブジェクトの作成)できない
  • .
  • 上のコードでは、DogとCatの2つのサブクラスがPetクラスのmake_voice抽象メソッドは書き換えられ、異なる実装バージョンが与えられました.
  • main関数でメソッドを呼び出すと、このメソッドはマルチステート挙動(同じメソッドで異なることをした)
  • を示す.

    総合ケース1(給与決済システム):
    """
                       、       
                ,              
    1.            15000 
    2.               ,   150 
    3.       1200         5%   
    """
    from abc import ABCMeta, abstractmethod
    
    
    class Employee(object, metaclass=ABCMeta):
        """  """
    
        def __init__(self, name):
            """
                 
    
            :param name:   
            """
            self._name = name
    
        @property
        def name(self):
            return self._name
    
        @abstractmethod
        def get_salary(self):
            """
                
    
            :return:   
            """
            pass
    
    
    class Manager(Employee):
        """    """
    
        def get_salary(self):
            return 15000.0
    
    
    class Programmer(Employee):
        """   """
    
        def __init__(self, name, working_hour=0):
            super().__init__(name)
            self._working_hour = working_hour
    
        @property
        def working_hour(self):
            return self._working_hour
    
        @working_hour.setter
        def working_hour(self, working_hour):
            self._working_hour = working_hour if working_hour > 0 else 0
    
        def get_salary(self):
            return 150.0 * self._working_hour
    
    
    class Salesman(Employee):
        """   """
    
        def __init__(self, name, sales=0):
            super().__init__(name)
            self._sales = sales
    
        @property
        def sales(self):
            return self._sales
    
        @sales.setter
        def sales(self, sales):
            self._sales = sales if sales > 0 else 0
    
        def get_salary(self):
            return 1200.0 + self._sales * 0.05
    
    
    def main():
        emps = [
            Manager('  '), Programmer('   '),
            Manager('  '), Salesman('  '),
            Salesman('  '), Programmer('  '),
            Programmer('  ')
        ]
        for emp in emps:
            if isinstance(emp, Programmer):
                emp.working_hour = int(input('   %s      : ' % emp.name))
            elif isinstance(emp, Salesman):
                emp.sales = float(input('   %s     : ' % emp.name))
            #      get_salary                    (  )
            print('%s     : ¥%s ' %
                  (emp.name, emp.get_salary()))
    
    
    if __name__ == '__main__':
        main()