从零开始的Linux运维屌丝之路,资源免费分享平台   运维人员首选:简单、易用、高效、安全、稳定、社区活跃的开源软件

44、面向对象 单继承 多继承

发布:蔺要红06-13分类: Python

继承

正常代码中 单继承 == 减少了代码的重复

继承表达的是一种 子类父类的关系

使用组合和继承的关键点、需要看是==是的关系 = 还是有的关系

1、老师有生日[组合]、不能说老师是生日 、教授是老师[继承]
2、查看是否有相同代码、相同代码即用继承

单继承

几个类之间的相同代码抽象出来,成为父类
子类自己没有的名字,就可以使用父类的方法和属性
如果子类自己有,先使用自己的
在类中使用self的时候,一定要看清楚self指向谁


一个类可以被多个类继承
一个类可以继承多个父类  #python里独有



# -*- coding:utf-8 -*-
class a(object):pass #父类,基类,超类
class b:pass
class a_son(a,b):pass #子类,派生类
class b_son(b):pass
#一个类可以被多个类继承
#一个类可以继承多个父类  #python里独有
print(a_son.__bases__) #查看继承了那些父类
print(b_son.__bases__) #查看继承了那些父类
print(a.__bases__)

#-------------------------------------------------------
D:\python\python.exe F:/运维笔记/python/面向对象/016面向对象继承.py
(<class '__main__.a'>, <class '__main__.b'>)
(<class '__main__.b'>,)
(<class 'object'>,)

对于之前的案例进行修改和进阶(创建角色、怪物、相互攻击)  节省代码量、重复的属性可以放到父类、
 
# -*- coding:utf-8 -*-
class Animal:
    def __init__(self,name,hp,aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr
class Dog(Animal):
    def bite(self,person):
        person.hp -= self.aggr
        print('%s攻击了%s,%s掉了%s的血' %(self.name,person.name,person.name, self.aggr))
class Person(Animal):
    def attack(self,dog):
        dog.hp -= self.aggr
        print('%s攻击了%s,%s掉了%s的血' %(self.name,dog.name,dog.name, self.aggr))
gouzi = Dog('树精',1000,200,)
nezha = Person('哪吒',1000,300,)
print(gouzi.__dict__)
print(nezha.__dict__)

#D:\python\python.exe F:/运维笔记/python/面向对象/017面向对象继承02.py
{'name': '树精', 'hp': 1000, 'aggr': 200}
{'name': '哪吒', 'hp': 1000, 'aggr': 300}

父类中没有的属性、在子类中出现,叫做派生属性
父类中没有的方法、在子类中出现,叫做派生方法

只要是子类的对象调用方法,子类和父类中都有的话,一定用子类的,子类中没有才找父类,如果父类也没有则报错
如果还想用父类的、则需要单独调用,需要传self参数


Animal.__init__(self,name,hp,aggr)   方法一调用父类
super().__init__                      方法二调用父类


    super() 不仅可以再类的内部使用,也可以再类的外部使用
    super()内部使用: super().__init__(name,hp,aggr) #不需要传类名
    super()外部使用:super(Dog,gouzi).eat() #需要传类名字和对象名


 
#方法一调用父类 Animal.__init__(self,name,hp,aggr)
class Animal:
    def __init__(self,name,hp,aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr
    def eat(self):
        self.hp += 100
        print('%s 使用了金疮药,血量增加到 %s' % (self.name, self.hp))
class Dog(Animal):
    def __init__(self,name,hp,aggr,kind):
        Animal.__init__(self,name,hp,aggr) #Animal.__init__(self,name,hp,aggr) #方法一调用父类
        self.kind = kind  #派生属性
    def eat(self):
        Animal.eat(self)  #如果既想使用父类原本的功能,也想实现新的功能,则需要在子类中调用父类
        self.teeth = 2
        print('%s 使用了金疮药,增加两颗牙齿' % (self.name))
    def bite(self,person):
        person.hp -= self.aggr
class Person(Animal):
    def __init__(self,name,hp,aggr,sex,money):
        Animal.__init__(self, name, hp, aggr)
        self.sex = sex  #派生属性
        self.money = 0  #派生属性
    def eat(self):
        self.hp += 100
        print('%s 使用了金疮药,血量增加到 %s' % (self.name, self.hp))
    def attack(self,dog):  #派生方法
        dog.hp -= self.aggr
    def get_weapon(self,weapon):  #派生方法
        if self.money >= weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr
        else:
            print('金币不足')
class Weapon:
    def __init__(self,name,aggr,njd,price):
        self.name = name
        self.aggr = aggr
        self.njd = njd
        self.price = price
    def hand18(self,person):
        if self.njd > 0:
            person.hp -= self.aggr*2
            self.njd -= 1
        else:
            print("您的武器坏了")
gouzi = Dog('哮天犬',999,200,'taidi')
nezha = Person('哪吒',1999,300,'女',0)
print(gouzi.__dict__)
w = Weapon('打狗棒',200,3,998)
gouzi.eat()
nezha.eat()
print(gouzi.hp)
print(nezha.hp)
print(gouzi.__dict__)

#D:\python\python.exe F:/运维笔记/python/面向对象/017面向对象继承03方法一.py
{'name': '哮天犬', 'hp': 999, 'aggr': 200, 'kind': 'taidi'}
哮天犬 使用了金疮药,血量增加到 1099
哮天犬 使用了金疮药,增加两颗牙齿
哪吒 使用了金疮药,血量增加到 2099
1099
2099
{'name': '哮天犬', 'hp': 1099, 'aggr': 200, 'kind': 'taidi', 'teeth': 2}
 
# -*- coding: UTF-8 -*-
#super().__init__  方法二调用父类
#super() 不仅可以再类的内部使用,也可以再类的外部使用
#super()内部使用: super().__init__(name,hp,aggr) #不需要传类名
#super()外部使用:super(Dog,gouzi).eat() #需要传类名字和对象名
class Animal:
    def __init__(self,name,hp,aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr
    def eat(self):
        self.hp += 100
        print('%s 使用了金疮药,血量增加到 %s' % (self.name, self.hp))
class Dog(Animal):
    def __init__(self,name,hp,aggr,kind):
        super().__init__(name,hp,aggr)
        self.kind = kind  #派生属性
    def eat(self):
        Animal.eat(self)  #如果既想使用父类原本的功能,也想实现新的功能,则需要在子类中调用父类
        self.teeth = 2
        self.hp += 100
        print('%s 使用了金疮药,增加两颗牙齿' % (self.name))
    def bite(self,person):
        person.hp -= self.aggr
class Person(Animal):
    def __init__(self,name,hp,aggr,sex,money):
        Animal.__init__(self, name, hp, aggr)
        #super().__init__(name,hp,aggr)
        self.sex = sex  #派生属性
        self.money = 0  #派生属性
    def eat(self):
        self.hp += 100
        print('%s 使用了金疮药,血量增加到 %s' % (self.name, self.hp))
    def attack(self,dog):  #派生方法
        dog.hp -= self.aggr
    def get_weapon(self,weapon):  #派生方法
        if self.money >= weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr
        else:
            print('金币不足')
class Weapon:
    def __init__(self,name,aggr,njd,price):
        self.name = name
        self.aggr = aggr
        self.njd = njd
        self.price = price
    def hand18(self,person):
        if self.njd > 0:
            person.hp -= self.aggr*2
            self.njd -= 1
        else:
            print("您的武器坏了")
gouzi = Dog('哮天犬',999,200,'taidi')
nezha = Person('哪吒',1999,300,'女',0)
w = Weapon('打狗棒',200,3,998)
super(Dog,gouzi).eat() #在父类和子类都有相同方法,仅执行父类
print(gouzi.hp)
gouzi.eat()         ##在父类和子类都有相同方法,父类和子类都执行
print(gouzi.hp)

#D:\python\python.exe F:/运维笔记/python/面向对象/017面向对象继承03方法二.py
哮天犬 使用了金疮药,血量增加到 1099
1099
哮天犬 使用了金疮药,血量增加到 1199
哮天犬 使用了金疮药,增加两颗牙齿
1299


多继承
 
多继承中:子类的对象调用一个方法,默认就近原则

新式类中:广度优先
经典类:深度优先

python2.7 新式类和经典类共存,新式类要继承object
python3   只有新式类,默认继承object
经典类和新式类还有一个区别:mro方法只在新式类中存在 super 只在python3中存在
类名.mro() 方法:查看广度优先的继承顺序

super本质:不是直接找父类,根据广度优先的继承顺序查找上一个类

python3:


实例:

print(D.mro())  #打印继承顺序

class F:
    def func(self):print('F')
class A(F):pass
    #def func(self):print('A')
class B(A):pass
    #def func(self):print('B')
class E(F):#pass
    def func(self):print('E')
class C(E):pass
    #def func(self):print('C')
class D(B,C):pass
    #def func(self):print('D')
d = D()
d.func()
print(D.mro())

D:\python\python.exe F:/运维笔记/python/面向对象/018面向对象继承03多继承.py
E
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>]

#super本质:不是直接父类,而是根据调用者的节点位置的广度优先顺序来的
 
#super本质:不是直接父类,而是根据调用者的节点位置的广度优先顺序来的
class A:
    def func(self):
        print('A')#9
class B(A):
    def func(self):#5
        super().func()#6
        print('B')#11
class C(A):
    def func(self):#7
        super().func()#8
        print('C')#10
class D(B,C):
    def func(self): #3
        super().func()#4
        print('D')#12
d = D() #1
d.func()#2
 
温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,如有侵权我会在24小时之内删除!

欢迎使用手机扫描访问本站