ホームページ  >  記事  >  バックエンド開発  >  Python オブジェクト指向における継承とは何かを理解するための 1 つの記事

Python オブジェクト指向における継承とは何かを理解するための 1 つの記事

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼転載
2019-08-28 17:40:022940ブラウズ

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 &#39;__main__.Father1&#39;>,)
(<class &#39;__main__.Father1&#39;>, <class &#39;__main__.Father2&#39;>)

2. 継承と抽象化

抽象化は 2 つのレベルに分かれています:

1. オバマとメッシをカテゴリ別に比較する部分。

2. 人間、豚、犬の 3 つのカテゴリのより類似した部分を親カテゴリに抽出します。

抽象化の主な機能は、カテゴリを分割することです (懸念事項を分離し、複雑さを軽減できます)

Python オブジェクト指向における継承とは何かを理解するための 1 つの記事

継承:

は抽象化の結果に基づいており、プログラミング言語で実装するには、継承によって抽象構造を表現する前に、まず抽象化のプロセスを経る必要があります。

抽象化は、分析と設計のプロセスにおける単なるアクションまたはテクニックであり、それを通じてクラスを取得できます。

Python オブジェクト指向における継承とは何かを理解するための 1 つの記事

class animal():   # 定义父类
    country  =  &#39;china&#39;     # 这个叫类的变量
    def __init__(self,name,age):
        self.name=name   # 这些又叫数据属性
        self.age=age
    def walk(self):         # 类的函数,方法,动态属性
        print(&#39;%s is walking&#39;%self.name)
    def say(self):
        pass
class people(animal):  # 子类继承父类
    pass
class pig(animal):    # 子类继承父类
    pass
class dog(animal):  # 子类继承父类
    pass
aobama=people(&#39;aobama&#39;,60)   # 实例化一个对象
print(aobama.name)
aobama.walk()
===================
aobama
aobama is walking

3. 派生

1. 親クラスに基づいてサブクラスを生成し、生成されたサブクラスは派生種類と呼ばれます。

2. 親クラスに存在しないメソッドはサブクラスに存在し、このようなメソッドを派生メソッドと呼びます。

3. 親クラスに存在し、サブクラスにも存在するメソッドをメソッドの書き換え(つまり、親クラスのメソッドを書き換えること)と呼びます。

関連する推奨事項: 「

Python ビデオ チュートリアル

例 1

class 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=&#39;Demacia&#39;   # 子类衍生出的变量
    def attack(self, enemy):   # 跟父类的 attack 重名,对象调用的时候以子类的为准
        pass
    def fire(self):    # 父类没有 fire,这里 fire 属于派生出来的东西
        print(&#39;%s is firing&#39; %self.nickname)
class Riven(Hero):
    camp=&#39;Noxus&#39;
g1=Garen(&#39;garen&#39;,18,200)
r1=Riven(&#39;rivren&#39;,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(&#39;Hero attack&#39;)
class Garen(Hero):
    camp = &#39;Demacia&#39;
    def attack(self, enemy): #self=g1,enemy=r1
        # self.attack(enemy) #g1.attack(r1),这里相当于无限递归
        Hero.attack(self,enemy)  # 引用 父类的 attack,对象会去跑 父类的 attack
        print(&#39;from garen attack&#39;)  # 再回来这里
    def fire(self):
        print(&#39;%s is firing&#39; % self.nickname)
class Riven(Hero):
    camp = &#39;Noxus&#39;
g1 = Garen(&#39;garen&#39;, 18, 200)
r1 = Riven(&#39;rivren&#39;, 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(&#39;from Hero attack&#39;)
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(&#39;from Garen attack&#39;)
    def fire(self):  # 在这里定义新的功能
        print(&#39;from Garen fire&#39;)
g1=Garen(&#39;garen&#39;,18,200,&#39;人在塔在&#39;)
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(&#39;from Hero attack&#39;)
        obj.life -= self.gongji
class Garen(Hero):   # 使用 super方式需要继承
    camp = &#39;Demacia&#39;
    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(&#39;from Garen fire&#39;)
g1 = Garen(&#39;garen1&#39;, 18, 200)
g2 = Garen(&#39;garen2&#39;, 20, 100)
print(g2.life)
g1.attack(g2)
print(g2.life)
100
from Hero attack
82

例 2

class A:
    def f1(self):
        print(&#39;from A&#39;)
        super().f1()    
        # 这种不需要继承也可以使用到 super,为什么,要看 C的 MRO表
class B:
    def f1(self):
        print(&#39;from B&#39;)
class C(A,B):
    pass
print(C.mro())
#[<class &#39;__main__.C&#39;>,
# <class &#39;__main__.A&#39;>,
# <class &#39;__main__.B&#39;>, #  B在A的后面,当A指定 super().f1 会找到 B的 f1
# <class &#39;object&#39;>]
c=C()
c.f1()

構成:

ソフトウェア継承に加えて、もう 1 つの重要な再利用方法、つまり合成があります。

Composition: あるオブジェクトのデータ属性は別のオブジェクトであり、これを組み合わせと呼びます。

class Equip: #武器装备类
    def fire(self):
        print(&#39;release Fire skill&#39;)
class Riven: #英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类
    camp=&#39;Noxus&#39;
    def __init__(self,nickname):
        self.nickname=nickname
        self.equip=Equip() #用Equip类产生一个装备,赋值给实例的equip属性
r1=Riven(&#39;锐雯雯&#39;)
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(&#39;<%s %s %s>&#39; %(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(&#39;egon&#39;,18,&#39;male&#39;,&#39;沙河霸道金牌讲师&#39;)
s1=Student(&#39;牛榴弹&#39;,18,&#39;female&#39;)
python=Course(&#39;python&#39;,&#39;3mons&#39;,3000.0)
linux=Course(&#39;python&#39;,&#39;3mons&#39;,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(&#39;文本数据的读取方法&#39;)
    def write(self):
        print(&#39;文本数据的读取方法&#39;)
class Sata(Interface): #磁盘,具体实现read和write
    def read(self):
        print(&#39;硬盘数据的读取方法&#39;)
    def write(self):
        print(&#39;硬盘数据的读取方法&#39;)
class Process(Interface):
    def read(self):
        print(&#39;进程数据的读取方法&#39;)
    def write(self):
        print(&#39;进程数据的读取方法&#39;)

上記のコードはインターフェースにしか見えませんが、実際にはインターフェースの役割を果たしているわけではなく、サブクラスはインターフェースを実装する必要がないため、抽象クラスが使用されます。

6. 抽象クラス

サブクラスは抽象クラスのメソッドを継承する必要があり、そうでない場合はエラーが報告されます。

抽象クラスとは何ですか?

Java と同様、Python にも抽象クラスの概念がありますが、これもモジュールの助けを借りて実装する必要があります。抽象クラスは特別なクラスです。その特徴は、継承され、インスタンス化できません

なぜ抽象クラスが必要なのでしょうか?

同じ内容を持つ一連のオブジェクトからクラスが抽出される場合、データ属性や関数属性を含む同じ内容を持つ一連のクラスから抽象クラスが抽出されます。

比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。你永远无法吃到一个叫做水果的东西。

从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

抽象类与接口

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。

例1

import abc
#抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们
class Animal(metaclass=abc.ABCMeta):   # 抽象类是用来被子类继承的,不是用来实例化的
    tag=&#39;123123123123123&#39;
    @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__ = &#39;Linhaifeng&#39;
#一切皆文件
import abc #利用abc模块实现抽象类
class All_file(metaclass=abc.ABCMeta):
    all_type=&#39;file&#39;
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def read(self):
        &#39;子类必须定义读功能&#39;
        pass
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def write(self):
        &#39;子类必须定义写功能&#39;
        pass
# class Txt(All_file):
#     pass
#
# t1=Txt() #报错,子类没有定义抽象方法
class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(&#39;文本数据的读取方法&#39;)
    def write(self):
        print(&#39;文本数据的读取方法&#39;)
class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(&#39;硬盘数据的读取方法&#39;)
    def write(self):
        print(&#39;硬盘数据的读取方法&#39;)
class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(&#39;进程数据的读取方法&#39;)
    def write(self):
        print(&#39;进程数据的读取方法&#39;)
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 サイトの他の関連記事を参照してください。

声明:
この記事はjianshu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。