個人的な使用へのアクセスが間違っている場合にのみ、また私を修正してください。
オブジェクト指向プログラミングは、プログラミングであるデザイン。オブジェクトの基本的なプログラムのようなユニットは、オブジェクトが含まれているデータとの運用データ機能。
このデザインのアイデアは、自然から来ています。そのため自然の中で、クラス(クラス)と例(インスタンス)の概念は非常に自然です。クラスは抽象的概念であり、例えば、私たちはクラスの選手定義:クラスプレーヤーを、(インスタンス)選手の概念を指し、およびインスタンス例えば、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())
ビューの呼び出し側の視点から、限り、私は入力のインスタンスを作成するときのように
name
、age
。そしてこの方法は、私が欲しいものを手に入れると呼ばれています。内部の特定のクラスを達成するためにどのように、私が管理する必要はありません。
アクセス制限
前述のクラスとインスタンスでは、クラス内の属性とメソッドを有することができることを学びました。そして、外部コードもあり自由に変更するには、インスタンスのプロパティを。実際には、これは安全ではない、と我々はすべき避けるような操作を。これは、民間へのパブリックから変更され、この変数を取るています。
プロパティの民営化
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
プロパティが民営化された後、それを取得することはできません。
買収、資産の民営化を変更します
実際には非常に単純な、それはによってである
get
、set
方法。今クラスに追加しget_name
、get_age
方法、およびset_name
、set_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
私たちは、フロントへのアクセスを制限するために言及しました。変数間の関係。私たちは、使用
get
、set
方法を。これは、プロパティを直接ではなく、とても便利少し複雑に見えます。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
上記の結果の動作の観点から、動的にプログラムを修正することができるバッチ式のメタクラスを使用することによって、彼らは、いくつかの修正に焦点を当てます。この機能は、いくつかの基本的なフレームワークを開発する際、プログラムはメソッドを追加するクラスのクラスを使用することによってドルの一定数のための一般的な機能を持っている必要があり非常に便利です。