研究ノート:のpython3のオブジェクト指向

個人的な使用へのアクセスが間違っている場合にのみ、また私を修正してください。

オブジェクト指向プログラミングは、プログラミングであるデザインオブジェクトの基本的なプログラムのようなユニットは、オブジェクトが含まれているデータとの運用データ機能

このデザインのアイデアは、自然から来ています。そのため自然の中で、クラス(クラス)例(インスタンス)の概念は非常に自然です。クラスは抽象的概念であり、例えば、私たちはクラスの選手定義:クラスプレーヤーを、(インスタンス)選手の概念を指し、およびインスタンス例えば、1の具体的なプレーヤーである:ヨルダン、デュラントは、彼らが特定されています。

:プログラミングの経験は、オブジェクト指向の三つの特徴を知っているカプセル化継承ポリモーフィズムを

  • クラスの例と

    クラスは抽象テンプレートです。例えば、プレイヤークラス。それぞれが同じメソッドを持って、オブジェクトの具体的な例です。

    • クラスの定義

      キーワードclass、クラス名が続く(大文字)、そして最後に(オブジェクト)彼は適切でない場合の選択に、継承されたクラスを示すことができobject、それはそうのようなものであるため、クラスの祖先

      class Player(object):
          pass
    • のインスタンスを作成します。

      同様の関数呼び出しでは、ここにあるクラス名()操作。

      # 创建实例1
      player1 = Player()
      # 创建实例2
      player2 = Player()
    • バインディング・プロパティ

      作成による__init__.py方法を、self代表インスタンス自体。

      class Player(object):
      
          def __init__(self, name, age):
              self.name = name
              self.age = age

      方法により財産を取得するオブジェクト。プロパティ

      # 创建实例1
      player1 = Player("Jordan", 45)
      # 获取属性
      name = player1.name
      age = player1.age
    • パッケージ

      今、私たちは、インスタンスは、これらの属性を持つことができることを知っています。直接クラス内の定義のデータへのアクセス機能、彼ら「データ」になるように、パッケージまで。そして、この方法は、クラスの関数です。

      印刷名の実装、年齢

      class Player(object):
      
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def print_name_age(self):
              print("%s, %d"%(self.name, self.age))
      
      player1 = Player("Jack", "30")
      print(player1.print_name_age())

      ビューの呼び出し側の視点から、限り、私は入力のインスタンスを作成するときのようにnameageそしてこの方法は、私が欲しいものを手に入れると呼ばれています。内部の特定のクラスを達成するためにどのように、私が管理する必要はありません。

  • アクセス制限

    前述のクラスとインスタンスでは、クラス内の属性とメソッドを有することができることを学びました。そして、外部コードもあり自由に変更するには、インスタンスのプロパティを。実際には、これは安全ではない、と我々はすべき避けるような操作を。これは、民間へのパブリックから変更され、この変数を取るています。

    • プロパティの民営化

      Pythonでは、2つのアンダースコアを使用すると、__私有財産を表すことができます。私たちの選手クラスの継続的な改善。

      class Player(object):
      
          def __init__(self, name, age):
              self.__name = name
              self.__age = age
      
          def print_name_age(self):
              return "%s, %d" % (self.__name, self.__age)
      
      
      player1 = Player("Jack", 30)
      print(player1.__name)   # ERROR 

      プロパティが民営化された後、それを取得することはできません。

    • 買収、資産の民営化を変更します

      実際には非常に単純な、それはによってであるgetset方法。今クラスに追加しget_nameget_age方法、およびset_nameset_age方法。私達のプレーヤーのクラスを変更し続けています。

      class Player(object):
      
          def __init__(self, name, age):
              self.__name = name
              self.__age = age
      
          def get_name(self):
              return self.__name
      
          def get_age(self):
              return self.__age
      
          def set_age(self, age):
              self.__age = age
      
          def print_name_age(self):
              return "%s, %d" % (self.__name, self.__age)
      
      
      player1 = Player("Jack", 30)
      player1.set_age(100)
      print(player1.get_name())       # Jack
      print(player1.get_age())        # 100

      明らかに、変更機能を実現しています。メソッドを追加できませんでした、あなたが直接、今多少余計なメソッドを追加、取得、変更することができます。実際の方法は追加しないで、目指す無効なパラメータを渡す避けるために、パラメータの検査を行うことです。

       def set_age(self, age):
              if 0 <= age <= 100:
                  self.__age = age
              else:
                  raise ValueError('bad score')

      もちろん、実際の開発プロジェクトでは、あなたは、アンダースコアインスタンスのプロパティの先頭が表示されます_nameアクセスはアクセス可能ですが、プライベートとしてそれを参照してください。

      あなたが書いていない場合は最後に、getメソッドを呼び出すことはできません、もちろんあなたは、Pythonインタプリタ、することができますので、__name属性はなり_Player__nameしかし、私はあなたが忘れ示唆しています。お勧めできません

  • 継承とポリモーフィズム

    • 受け継ぎます

      クラス定義では、すべてのクラスを継承することができる、と述べていたobject同じクラスは、私たちの独自の定義を継承することができます。

      例えば、私が定義Animal動物が持っている、動物run()方法。

      私は犬や猫を記述する場合、私はこの動物を継承できるようになります。

      class Animal(object):
      
          def run(self):
              return "animal is running"
      
      class Dog(Animal):
          pass
      
      class Cat(Animal):
          pass

      継承のメリット:サブクラスは、犬や猫が既に持っていることを意味し、親クラスのすべての機能を得ることができますrun()行く方法を。

      上記の例に基づいて、我々は、呼び出しに行きます。

      dog = Dog()
      print(dog.run())
      
      cat = Cat()
      print(cat.run())
      
      # output
      animal is running
      animal is running

      ロジックに対応するために、我々は、コードを変更し続けます

      class Animal(object):
      
          def run(self):
              return "animal is running"
      
      class Dog(Animal):
      
          def run(self):
              return "dog is running"
      
      class Cat(Animal):
      
          def run(self):
              return "cat is running"
      
      dog = Dog()
      print(dog.run())
      
      cat = Cat()
      print(cat.run())
      
      # output:
      dog is running
      cat is running

      これは、実行時に誰であるか、非常に明確です。

      サブクラスとスーパークラスは同じに存在する場合run()、時間方法。親クラスをカバーしているサブクラスです。

    • ポリモーフィズム

      手始めに、多型または理解することが少し難しいが、我々は唯一のプログラムを通じて強化し続けることができます。

      class Animal(object):
      
          def run(self):
              return "animal is running"
      
      class Dog(Animal):
      
          pass
      
      class Cat(Animal):
      
          def run(self):
              return "cat is running"
      
      
      dog = Dog()
      print(isinstance(dog, Dog))
      print(isinstance(dog, Animal))
      
      # output:
      True
      True

      上記のコードから分かるようdogに属しDogタイプ、およびに属するAnimalタイプ。同様に、catそれは同じです。

      オブジェクトが持っている場合、我々は、オブジェクトを渡すとrun()実装には、この方法を。ない場合は、親クラスの呼び出しに行くrun()方法を。これは多型です。

      これは動的言語で、動的言語は、インスタンスメソッドを呼び出して、限り、あなたは呼び出すことができる方法、正確なパラメータがあるとして、タイプをチェックしません。

      勉強を続けて

      import json
      
      f = open('/path/to/file.json', 'r')
      print(json.load(f))
      
      class Students(object):
          def __init__(self, strlist):
              self.strlist = strlist
      
          def read(self):
              return(self.strlist)
      
      s = Students('["Tim", "Bob", "Alice"]')
      
      print(json.load(s))

      以来、fオブジェクトが持つread()メソッドを、そしてsオブジェクトが持っているread()方法を。

      したがって、任意のオブジェクトは、限りと考えることができるread()メソッドが呼び出されたファイルオブジェクト、渡すことができますjson.load()

  • オブジェクト情報の取得

    オブジェクトの種類の分析:isinstance()機能を、オブジェクトの取得type()タイプ:

    オブジェクトのプロパティとメソッドを取得します:dir()機能を。

  • 属性とクラス属性の例

    私たちは、あなたが使用することができ、前述の__init__.py方法のインスタンスを結合属性。

    同様に、クラスは属性を持つことができます。そして、すべてこのプロパティを分類します。

    class Player(object):
    
        country = "chinese"

    すべての分類が、我々は、クラス属性を定義し、それはクラスのインスタンスであるときにアクセスすることができます。

    上記のテスト引数

    p = Player()          # 创建实例p
    
    print(p.country)       # 打印country属性,因为实例并没有country属性,所以会继续查找类属性
    
    print(Player.country) # 打印类属性
    
    p.country = "small Japan" # 给实例绑定country属性
    print(p.country)          # 由于实例属性的优先级高于类属性,因此屏蔽了类的属性
    
    print(Player.country)     # 但是类属性并未消失。还是可以访问
    
    del p.country             # 删除实例绑定的属性之后
    
    print(p.country)          # 再去调用,就只能委屈得到类属性了。

    注意:実際のプログラミングは、やるときではないため、インスタンス属性クラス属性使用して同じ名前

  • クラスメソッド

    言及した以前のインスタンスは属性とメソッドを持っているとして、属性の種類があり、方法もあります。

    class Person(object):
    
        count = 0
    
        @classmethod
        def how_many(cls):
            return cls.count
    
        def __init__(self, name):
            self.name = name
            Person.count = Person.count + 1
    
    print(Person.how_many())
    p1 = Person('Bob')
    print(Person.how_many()) 

    それはマーキングによって、見ることができます@classmethodに特異的に結合する、Personというよりも、クラス、クラス、インスタンスを。入ってくるクラスメソッドクラス自体の最初のパラメータは、通常、パラメータ名として命名cls以上、cls.count実際には同等Person.count

    それはむしろインスタンス上で呼び出すよりも、クラスの呼び出しであるので、したがって、クラスメソッドはできません得る任意のインスタンス変数は、あなただけ取得することができ、参照クラスを

  • __slots__

    あなたが動的にバインドすることができますので、我々は制限する必要があるため、この方法は、プロパティのインスタンスを制限するために使用されます。次の手順例:

    class Student(object):    
      __slots__ = ('name', 'age')
    
    s = Student()
    s.name = "Jack"
    s.age = 20
    s.score = 90      # AttributeError

    上記の手順を見ることができます:タプル定義が可能に結合属性名、以来、スコアが置かれていない__slots__で、それが結合できないスコアプロパティを。そこならば学生のサブクラスを持って、slots属性定義されたサブクラスは効果がありません。

  • @property

    私たちは、フロントへのアクセスを制限するために言及しました。変数間の関係。私たちは、使用getset方法を。これは、プロパティを直接ではなく、とても便利少し複雑に見えます。

    Pythonは両方のパラメータ検査は行われませんこと、および変数は、このような簡単な方法を属性類似のクラスにアクセスすることができますか?それはそこにあります。

    デコレータのように動的にクラスメソッド、同じ関数デコレータのための機能に機能を追加することができます。

    Pythonの組み込みの@propertyデコレータは、責任ある方法になるというプロパティで。たとえば、次の手順

    class Student(object):
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value
    
    s = Student()
    s.score = 60
    print(s.score)

    @property役割は、プロパティのゲッターメソッドになるだけ追加することで@property、この時、でそれを@property今度は別のデコレータを作成@score.setterする責任セッターメソッドをプロパティの割り当てとなり、私たちは制御可能な特性を持っています操作。コードを見て、s.score = 60実際の変換はs.set_score(60)s.score実際の変換されましたs.get_score()実際には、本質またはgetterメソッドとsetterメソッドによっては達成するようにします。

  • 列挙型クラス

    いくつかのケースでは、クラスオブジェクトは、限定されて固定されている遊星型限り、現在の8人の被験者;オブジェクト12と月のクラス、及びそのような固定の有限の例として、それだけで4つのオブジェクトを有し、そのような季節のクラスとして、クラスが呼び出された列挙クラス

    • 定義する列挙クラス

      列挙型()関数を使用して作成しました。最初のパラメータは、クラス名の列挙クラスであり、2番目のパラメータは、列挙値のタプルの形式です。

      import enum
      
      Season = enum.Enum('Season', ('SPRING', 'SUMMER', 'FALL', 'WINTER'))
    • アクセス列挙値

      各メンバーには名前、値2つのプロパティがあります。

      # 直接访问指定枚举
      print(Season.SPRING)
      # 访问枚举成员的变量名
      print(Season.SPRING.name)
      # 访问枚举成员的值
      print(Season.SPRING.value)
      
      # output:
      Season.SPRING
      SPRING
      1

      また、改善するための__members__dictの辞書を返すプロパティを、。

      for name, member in Season.__members__.items():    
          print(name, '=>', member, ',', member.value)
      
      # output:
      SPRING => Season.SPRING , 1
      SUMMER => Season.SUMMER , 2
      FALL => Season.FALL , 3
      WINTER => Season.WINTER , 4
  • タイプ()

    言及した先に、タイプ()関数は、変数の種類を表示することはできますが、タイプを(使用する場合)直接のクラスの種類を見ますか?次のコードを考えてみます。

    class Role:
        pass
    
    r = Role()
    # 查看变量r的类型
    print(type(r))        # <class '__main__.Role'>
    # 查看Role类本身的类型
    print(type(Role))     # <class 'type'>

    カードは、クラス自体は、ロールタイプに入力され、上記の出力から分かります。役割クラスのタイプを理解するためにどのように、発音は少し難しいこの文は、入力しているのですか?

    Pythonインタプリタの観点から、クラスの役割のクラス定義を使用した場合、プログラムは、特定のオブジェクト(オブジェクト・クラス・タイプ)を定義すると理解され、オブジェクト変数の役割に割り当てられています。したがって、すべてのクラスのクラス定義を使用したプログラムは、クラス型のインスタンスです。

    Pythonは、実際にフルタイプ()関数オブジェクトタイプを作成する(等価クラスのコンストラクタ関数を入力する)許可され、クラスタイプのインスタンスであるため、クラス・タイプは、動的にクラスを作成するPythonのように()関数を使用することができます。次の手順例:

    def fn(self):    
      print('fn函数')
    
    # 使用type()定义Dog类
    Dog = type('Dog', (object,), dict(walk=fn, age=6))
    # 创建Dog对象
    d = Dog()
    # 分别查看d、Dog的类型
    print(type(d))
    print(type(Dog))
    d.walk()
    print(Dog.age)
    
    #output:
    <class '__main__.Dog'>
    <class 'type'>
    fn函数
    6

    パラメータは三つのクラスを定義指定するタイプを()を使用します:

    1、パラメータ:作成したクラス名。

    2、二つのパラメータ:クラスのセットは、親クラスを継承します。Pythonは多重継承をサポートしているので、ので、ここではその複数の親クラスを指定したタプル。でも実際には、親が、だけでなく、(カンマ以上でなければならない)タプル構文を使用する必要があります。

    3、三つのパラメータ:クラス変数とバインドクラスの辞書オブジェクトのための方法。どの辞書の値が通常の値であれば、それはクラス変数を表し、辞書のキー変数やメソッド名のようなものです。値が辞書の関数であるならば、方法です。

    このように、ライン5犬のコードは、オブジェクトクラスを継承するクラスを定義し、クラスは、徒歩()メソッドと可変年齢クラスを定義しています。

  • 元类

    メタクラスは、あなたが理解していない場合、その後、あなたが学ばない、プロセス全体を読んだ後、理解することは難しいことではありません。

    実際に、それはあなたが複雑なクラスがメタクラス(分類)によって必要とされて作成したい場合は、動的に、比較的単純なクラスを作成するために適用されるとき、タイプ()関数の前で言えば。

    元のクラスは、単にクラスは、クラスを作成することであると理解することができます。

    • 定義されたメタクラス

      継承と型クラスを作成する必要があり、デフォルトの命名規則は、メタクラス最後に、クラス名を作ることです。また、要素を定義し、実装する必要がある__new__()メソッドを(戻り値が存在しなければなりません)。クラスが作成された元のクラスなので、__new__()この方法は、新しいクラスを生成するために使用される、呼び出されます。

      # 定义Item元类,继承type
      class ItemMetaClass(type):
          # cls代表动态修改的类
          # name代表动态修改的类名
          # bases代表被动态修改的类的所有父类
          # attr代表被动态修改的类的所有属性、方法组成的字典
          def __new__(cls, name, bases, attrs):
              # 动态为该类添加一个cal_price方法
              attrs['cal_price'] = lambda self: self.price * self.discount
              return type.__new__(cls, name, bases, attrs)

      上記の手順では、ターゲットクラスを動的cal_priceメソッドを追加するには、このメソッドをオーバーライドします。

    • クラスのメタクラスを作成します。

      # 定义Book类
      class Book(metaclass=ItemMetaClass):
          __slots__ = ('name', 'price', '_discount')
          def __init__(self, name, price):
              self.name = name
              self.price = price
          @property
          def discount(self):
              return self._discount
          @discount.setter
          def discount(self, discount):
              self._discount = discount
      
      # 定义cellPhone类
      class CellPhone(metaclass=ItemMetaClass):
          __slots__ = ('price', '_discount' )
          def __init__(self, price):
              self.price = price
          @property
          def discount(self):
              return self._discount
          @discount.setter
          def discount(self, discount):
              self._discount = discount

      上記プログラムは、2つのクラスの携帯電話・PHSブックを定義し、2つのクラスの定義内の情報要素の種類を指定し、したがって、これら2つのクラスを作成Pythonインタプリタは、ItemMetaClassはの場合__new__、この方法を修正するために呼び出されます二つのクラス。

      したがって、これら2つのクラスがまだcal_price()メソッドの定義です。次のコードが検出されます。

      b = Book("Python基础教程", 89)
      b.discount = 0.75
      # 创建Book对象的cal_price()方法
      print(b.cal_price())
      cp = CellPhone(2399)
      cp.discount = 0.85
      # 创建CellPhone对象的cal_price()方法
      print(cp.cal_price())
      
      # output:
      66.75
      2039.1499999999999

      上記の結果の動作の観点から、動的にプログラムを修正することができるバッチ式のメタクラスを使用することによって、彼らは、いくつかの修正に焦点を当てます。この機能は、いくつかの基本的なフレームワークを開発する際、プログラムはメソッドを追加するクラスのクラスを使用することによってドルの一定数のための一般的な機能を持っている必要があり非常に便利です。

おすすめ

転載: www.cnblogs.com/lowkeyao/p/11311822.html