ホームページ >バックエンド開発 >Python チュートリアル >Python オブジェクト指向における継承とは何かを理解するための 1 つの記事
#1. 継承とは何ですか?
継承とは、クラス間の関係を指します。これは「現状関係」であり、その機能の 1 つは、コードの再利用の問題を解決することです。 継承は、新しいクラスを作成する方法です。Python では、新しく作成されたクラスは 1 つ以上の親クラスを継承できます。親クラスは、基本クラスまたはスーパー クラスと呼ばれることもあります。新しく作成されたクラスクラスやサブクラスの継承は、単一継承と多重継承に分けられます。class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass print(Son1.__bases__) # 查看所有继承的父类 print(Son2.__bases__) =============== (<class '__main__.Father1'>,) (<class '__main__.Father1'>, <class '__main__.Father2'>)
2. 継承と抽象化
抽象化は 2 つのレベルに分かれています: 1. オバマとメッシをカテゴリ別に比較する部分。 2. 人間、豚、犬の 3 つのカテゴリのより類似した部分を親カテゴリに抽出します。 抽象化の主な機能は、カテゴリを分割することです (懸念事項を分離し、複雑さを軽減できます)継承:
は抽象化の結果に基づいており、プログラミング言語で実装するには、継承によって抽象構造を表現する前に、まず抽象化のプロセスを経る必要があります。 抽象化は、分析と設計のプロセスにおける単なるアクションまたはテクニックであり、それを通じてクラスを取得できます。class animal(): # 定义父类 country = 'china' # 这个叫类的变量 def __init__(self,name,age): self.name=name # 这些又叫数据属性 self.age=age def walk(self): # 类的函数,方法,动态属性 print('%s is walking'%self.name) def say(self): pass class people(animal): # 子类继承父类 pass class pig(animal): # 子类继承父类 pass class dog(animal): # 子类继承父类 pass aobama=people('aobama',60) # 实例化一个对象 print(aobama.name) aobama.walk() =================== aobama aobama is walking
3. 派生
1. 親クラスに基づいてサブクラスを生成し、生成されたサブクラスは派生種類と呼ばれます。 2. 親クラスに存在しないメソッドはサブクラスに存在し、このようなメソッドを派生メソッドと呼びます。 3. 親クラスに存在し、サブクラスにも存在するメソッドをメソッドの書き換え(つまり、親クラスのメソッドを書き換えること)と呼びます。 関連する推奨事項: 「Python ビデオ チュートリアル 」
例 1class Hero: def __init__(self, nickname, aggressivity, life_value): self.nickname = nickname self.aggressivity = aggressivity self.life_value = life_value def attack(self, enemy): enemy.life_value -= self.aggressivity class Garen(Hero): # 子类继承 hero 父类 camp='Demacia' # 子类衍生出的变量 def attack(self, enemy): # 跟父类的 attack 重名,对象调用的时候以子类的为准 pass def fire(self): # 父类没有 fire,这里 fire 属于派生出来的东西 print('%s is firing' %self.nickname) class Riven(Hero): camp='Noxus' g1=Garen('garen',18,200) r1=Riven('rivren',18,200) # print(g1.camp) # print(r1.camp) # g1.fire() g1.attack(g1)例 2
class Hero: def __init__(self, nickname,aggressivity,life_value): self.nickname = nickname self.aggressivity = aggressivity self.life_value = life_value def attack(self, enemy): print('Hero attack') class Garen(Hero): camp = 'Demacia' def attack(self, enemy): #self=g1,enemy=r1 # self.attack(enemy) #g1.attack(r1),这里相当于无限递归 Hero.attack(self,enemy) # 引用 父类的 attack,对象会去跑 父类的 attack print('from garen attack') # 再回来这里 def fire(self): print('%s is firing' % self.nickname) class Riven(Hero): camp = 'Noxus' g1 = Garen('garen', 18, 200) r1 = Riven('rivren', 18, 200) g1.attack(r1) # print(g1.camp) # print(r1.camp) # g1.fire()
4. 組み合わせ再利用性
再利用性:方法 1: 継承せずに属性を再利用し、使用するクラスの属性に名前を付けます。class Hero: def __init__(self,nickname,gongji,life): self.nickname=nickname self.gongji=gongji self.life=life def attack(self,obj): print('from Hero attack') class Garen: def __init__(self,nickname,gongji,life,script): Hero.__init__(self,nickname,gongji,life) # 这里引用Hero类的 init,不用再自己从新定义一遍 init self.script=script # 父类 init 没有 script,这里是新加进来的属性 def attack(self,obj): # 在这里自己定义新的 attack,不再使用父类的 attack print('from Garen attack') def fire(self): # 在这里定义新的功能 print('from Garen fire') g1=Garen('garen',18,200,'人在塔在') print(g1.script) 人在塔在ヒント: 既存のクラスを使用して新しいクラスを作成すると、既存のソフトウェアの一部または大部分が再利用され、プログラミングの作業負荷が大幅に節約されます。これは、ソフトウェアの再利用とよく呼ばれます。独自のクラスを再利用できるだけでなく、また、標準ライブラリなどの他のクラスを継承して新しいデータ型をカスタマイズすることもできるため、ソフトウェア開発サイクルが大幅に短縮され、大規模なソフトウェア開発にとって非常に重要です。 注: g1.life のような属性参照の場合、life は最初にインスタンスから、次にクラスから、そして親クラスから…最上位の親クラスまで見つかります。 方法 2: 継承による例 1
class Hero(): def __init__(self, nickname, gongji, life): self.nickname = nickname self.gongji = gongji self.life = life def attack(self, obj): print('from Hero attack') obj.life -= self.gongji class Garen(Hero): # 使用 super方式需要继承 camp = 'Demacia' def __init__(self, nickname, gongji, life): super().__init__(nickname, gongji, life) def attack(self, obj): # 在这里自己定义新的 attack,不再使用父类的 attack super(Garen, self).attack(obj) # PY3中super可以不给参数,PY2中第一个参数必须是自己的类,self,可以使用 父类的方法,方法需要给参数就给参数 def fire(self): # 在这里定义新的功能 print('from Garen fire') g1 = Garen('garen1', 18, 200) g2 = Garen('garen2', 20, 100) print(g2.life) g1.attack(g2) print(g2.life) 100 from Hero attack 82例 2
class A: def f1(self): print('from A') super().f1() # 这种不需要继承也可以使用到 super,为什么,要看 C的 MRO表 class B: def f1(self): print('from B') class C(A,B): pass print(C.mro()) #[<class '__main__.C'>, # <class '__main__.A'>, # <class '__main__.B'>, # B在A的后面,当A指定 super().f1 会找到 B的 f1 # <class 'object'>] c=C() c.f1()
構成:
ソフトウェア継承に加えて、もう 1 つの重要な再利用方法、つまり合成があります。 Composition: あるオブジェクトのデータ属性は別のオブジェクトであり、これを組み合わせと呼びます。class Equip: #武器装备类 def fire(self): print('release Fire skill') class Riven: #英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类 camp='Noxus' def __init__(self,nickname): self.nickname=nickname self.equip=Equip() #用Equip类产生一个装备,赋值给实例的equip属性 r1=Riven('锐雯雯') r1.equip.fire() #可以使用组合的类产生的对象所持有的方法 release Fire skill
組み合わせの方法:
組み合わせと継承は、既存のクラスのリソースを効果的に利用するための重要な方法です。ただし、この 2 つの概念と使用シナリオは異なります。 1. 継承方法派生クラスと基底クラスの関係は継承によって確立され、白馬は馬であり人間であるというように、「ある」関係となります。は動物です。 クラス間に類似した関数が多数ある場合は、共通の関数を抽出して基底クラスにするのがよいでしょう。継承を使用するのがよいでしょう。たとえば、教師も人間であり、生徒も人間です。2. 組み合わせ方法 クラスと組み合わせクラスの関係は、組み合わせによって確立されます。たとえば、教授には誕生日がある、教授は Python と Linux のコースを教えているなど、「ある」関係です。 、教授には学生 s1 と s2 がいます。 、s3...class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class Course: def __init__(self,name,period,price): self.name=name self.period=period self.price=price def tell_info(self): print('<%s %s %s>' %(self.name,self.period,self.price)) class Teacher(People): def __init__(self,name,age,sex,job_title): People.__init__(self,name,age,sex) self.job_title=job_title self.course=[] self.students=[] class Student(People): def __init__(self,name,age,sex): People.__init__(self,name,age,sex) self.course=[] egon=Teacher('egon',18,'male','沙河霸道金牌讲师') s1=Student('牛榴弹',18,'female') python=Course('python','3mons',3000.0) linux=Course('python','3mons',3000.0) #为老师egon和学生s1添加课程 egon.course.append(python) egon.course.append(linux) s1.course.append(python) #为老师egon添加学生s1 egon.students.append(s1) #使用 for obj in egon.course: obj.tell_info()
5. インターフェイスと正規化された設計
a. インターフェイスを使用する理由は何ですか? インターフェースはクラスの共通関数群を抽出したものであり、インターフェースは関数の集合とみなすことができます。 次に、サブクラスにインターフェイス内の関数を実装させます。 これの重要性は正規化です。正規化とは、クラスが同じインターフェイスに基づいて実装されている限り、これらすべてのクラスによって生成されたオブジェクトが同じ方法で使用されることです。 正規化の利点は次のとおりです: 正規化により、ユーザーはオブジェクトのクラスを気にする必要がなくなり、これらのオブジェクトに特定の機能があることだけを知る必要があります。これはまさに地球です。ユーザーの使いにくさを軽減します。class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。 def read(self): #定接口函数read pass def write(self): #定义接口函数write pass class Txt(Interface): #文本,具体实现read和write def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(Interface): #磁盘,具体实现read和write def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(Interface): def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法')上記のコードはインターフェースにしか見えませんが、実際にはインターフェースの役割を果たしているわけではなく、サブクラスはインターフェースを実装する必要がないため、抽象クラスが使用されます。
6. 抽象クラス
サブクラスは抽象クラスのメソッドを継承する必要があり、そうでない場合はエラーが報告されます。抽象クラスとは何ですか?
Java と同様、Python にも抽象クラスの概念がありますが、これもモジュールの助けを借りて実装する必要があります。抽象クラスは特別なクラスです。その特徴は、継承され、インスタンス化できませんなぜ抽象クラスが必要なのでしょうか?
同じ内容を持つ一連のオブジェクトからクラスが抽出される場合、データ属性や関数属性を含む同じ内容を持つ一連のクラスから抽象クラスが抽出されます。比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。
抽象类与接口
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。
例1
import abc #抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们 class Animal(metaclass=abc.ABCMeta): # 抽象类是用来被子类继承的,不是用来实例化的 tag='123123123123123' @abc.abstractmethod # 如果子类没有我这个函数,主动抛出异常 def run(self): pass @abc.abstractmethod def speak(self): pass class People(Animal): def run(self): # 子类必须有抽象类里的装饰器下面的函数 pass def speak(self): pass peo1=People() # 实例化出来一个人 print(peo1.tag)
例2
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' #一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # # t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)
以上がPython オブジェクト指向における継承とは何かを理解するための 1 つの記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。