記事のディレクトリ
1.何が多型であります
マルチ状態が何であるかを理解するために、我々は最初のデータを入力し、少し説明をしなければなりません。私たちは、クラスを定義するとき、私たちは、実際にデータ型を定義します。私たちは、辞書には違いはありませんデータ型を定義して、そのようなSTR、リストとしてPythonのデータ型、付属しています:
a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型
変数を使用することができるタイプであるかどうかを判断isinstance()
決定します。
>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True
>>> isinstance(c, Dog)
True
bは、cは確かリスト、動物、犬3種類の対応と思われます。
しかし、待ってみてください:
>>> isinstance(c, Animal)
True
Cはちょうど犬、Cまたは動物です!
しかし、我々は犬cのインスタンスを作成するとき、我々はデータ型がはい犬cがあることを信じて、犬がダウン動物から継承されているので、これは、理にかなって、それについて考える、だけでなく、動物の本当のC 、犬はいつも動物されています!
だから、階層で、データ型が、それはまた、親として見ることができるデータの種類のサブクラスのインスタンスである場合。
しかし、その逆は真ではありません。
>>> b = Animal()
>>> isinstance(b, Dog)
False
犬は動物としてではなく、動物犬として見ることができます。
多型の利点を理解するために、我々はまだ型動物の変数を受け入れる関数を記述する必要があります。
def run_twice(animal):
animal.run()
animal.run()
私たちは動物のインスタンスを渡すと、run_twiceは()プリントアウトするには:
>>> run_twice(Animal())
Animal is running...
Animal is running...
私たちは犬のインスタンスを渡すと、run_twiceは()プリントアウトするには:
>>> run_twice(Dog())
Dog is running...
Dog is running...
我々は猫のインスタンスを渡すと、run_twiceは()プリントアウトするには:
>>> run_twice(Cat())
Cat is running...
Cat is running...
これは、平均何も見えませんが、我々はタイプ亀を定義した場合、また、動物に由来し、今それについて考えます:
class Tortoise(Animal):
def run(self):
print('Tortoise is running slowly...')
我々はrun_twice()、亀の入力インスタンスを呼び出すとき:
>>> run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...
あなたがする必要はありません、新しい動物のサブクラスがありますrun_twice()
実際には、関数やメソッドのパラメータとして任意の依存の動物は変更なしで正常動作している、任意の変更を行い、その理由は、ある多型。
多型の利点は、我々は犬、猫、亀を......渡す必要があるときに犬、猫、亀......すべての動物の種類、およびは、動物の種類に従っているので、我々は唯一、それを動物の種類を受信する必要があるということですそれはすることができます。動物タイプなのでrun()
方法、そのため、どのようなタイプで渡された、限りAnimalクラスまたはサブクラスとして、自動的に多形性の意味であるrun()メソッドの実際の型を呼び出します。
変数のために、私たちは、特定の呼び出しを()メソッドは、動物、犬、猫や亀の役割である、あなたが安全にrun()メソッドを呼び出すことができます正確にどのサブタイプを知らなくても、それは動物の種類であることを知っておく必要があり、および実行します呼び出し側はちょうどかかわらず、細部の、呼び出し、私たちは動物サブクラスの一種類を追加するときに、ちょうど正しく書くようにしてくださいrun()メソッドを作る:マルチステート本当の力で、実行時にオブジェクトの正確な型を決定することにより、オブジェクト、上、元のコードが呼び出される方法を制御しません。これが有名な「開閉」の原則です。
「開閉」の原則
へスプレッドオープン:許可する新しい動物のサブクラス;
用修正ブロッキングない:動物何も変更依存型run_twice()関数と同じように。
継承はまた、そのような関係の息子に父親に祖父からのような平地のダウンを、継承することができます。そして、任意のクラス、そして最終的には木の継承後方のように見えるルートクラスのオブジェクトを追跡することが可能です。たとえば、次の継承ツリー:
┌───────────────┐
│ object │
└───────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Animal │ │ Plant │
└─────────────┘ └─────────────┘
│ │
┌─────┴──────┐ ┌─────┴──────┐
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Dog │ │ Cat │ │ Tree │ │ Flower │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
2、動的言語の言語対静的
必要性は動物の種類を渡す場合(Javaなど)の静的型付け言語では、入ってくるオブジェクトがそうでない場合、あなたはrun()メソッドを呼び出すことはできません、種類の動物またはそのサブクラスでなければなりません。
Pythonなどの動的言語の場合、それは必ずしも動物のタイプに渡す必要がないであろう。私達はちょうど入ってくるオブジェクトがその上にrun()メソッドを持っていることを確認する必要があります。
class Timer(object):
def run(self):
print('Start...')
これは、それがアヒルのように見ることができる「アヒルのように見えるアヒルのように歩き、」それは厳格な継承階層限り、オブジェクトを必要としない、「ダックタイピング」の動的言語です。
Pythonの「ファイルオブジェクトは、」ダックタイピングの一種です。
実際のファイル・オブジェクトの場合は、その内容を返すread()メソッドを有します。しかし、多くのオブジェクトは、限り、read()メソッドとして、「ファイルオブジェクト」と考えられています。多くの機能は、メソッド)の引数は、「ファイルオブジェクト」で、あなたは実際のファイルオブジェクトを渡す必要はありません、任意のオブジェクトが実装(リード渡すことができ受けます。
概要
あなただけの独自の方法を追加する必要が再スクラッチ、サブクラスにはありませんので、あなたは親クラスのメソッドが適して上書きされずに置くことができ、直接引き継ぐ親クラスのすべての機能を継承することができます。
アヒル型は動的言語が必要であるような静的言語とは異なり連続を決定しています。
図3に示すように、Pythonの多型
相続、および変換のサブクラス型を持つクラスは、我々がからであれば、上向きのクラス型の父として見ることができるPerson
派生Student
してTeacher
、と書かれているwhoAmI()
方法を:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I am a Person, my name is %s' % self.name
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I am a Student, my name is %s' % self.name
class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course
def whoAmI(self):
return 'I am a Teacher, my name is %s' % self.name
関数の中で、私たちはあるならば、xは人、学生や教師かどうか、正しい結果をプリントアウトすることができますされ、変数xを受信します:
def who_am_i(x):
print x.whoAmI()
p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')
who_am_i(p)
who_am_i(s)
who_am_i(t)
結果:
I am a Person, my name is Tim
I am a Student, my name is Bob
I am a Teacher, my name is Alice
この動作が呼び出されますポリモーフィズム。
言い換えれば、メソッド呼び出しは、xの実際の型に作用します。
sの学生のタイプで、それは実際には、独自の持ってwhoAmI()
WHOAMI人からのメソッドとメソッドが継承が、コールはs.whoAmI()
、定義されていない場合は、常に独自の定義を見つけることが第一ですそして、継承チェーンのアップを見下ろしますあなたまで1つの親クラスを見つけます。
Python言語は動的であるので、従って、関数に渡されたwho_am_i(x)
パラメータxのは、必ずしも人一人のサブタイプまたはありません。例には、それが有する限り、任意のタイプのデータであるwhoAmI()
の方法。
class Book(object):
def whoAmI(self):
return 'I am a book'
これはダイナミックで(Javaなど)の静的な言語の最大の違いの一つです。動的言語は、限りの方法があるとして、パラメータを正しくタイプをチェックしません、あなたが呼び出すことができ、インスタンスメソッドを呼び出します。
タスク
Pythonは提供してopen()
ディスクファイルを開くための機能をしてFileオブジェクトを返します。Fileオブジェクトが持っているread()
ファイルの内容を読み取るための方法を:
例えば、ファイルから読み取り、JSON結果として解析。
import json
f = open('/path/to/file.json', 'r')
print json.load(f)
ためのPythonの動的な機能に、json.load()
必ずしもFileオブジェクトから内容を読み取ります。任意のオブジェクトは、限りread()
方法は、ファイルのようなオブジェクトと呼ばれる)(json.loadを通過することができます。
ファイルオブジェクト、書くようにしてください
文字列r'["Tim", "Bob", "Alice"]'
でファイルオブジェクトにパックされたjson.load()
解像度を。
コード
学生はちょうどクラスに追加するread()
方法、それはファイルオブジェクトになります。
import json
class Students(object):
def __init__(self,):
self.name = r'["Tim", "Bob", "Alice"]'
def read(self):
return self.name
s = Students()
print json.load(s)