Python学习之路---面向对象---继承

继承:继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以称为基类或超类,新建的类称为子类或派生类;

class A:pass
class B:pass
class A_son(A,B):pass # 可以继承多个类
class B_son(B):pass # 可以继承一个类
# 两个子类之间是没有关联的

注意:什么时候用组合,什么时候用继承

组合:什么有什么的关系     继承:什么是什么的关系

Python中类的继承分为单继承和多继承。注意:常用单继承,多继承主要用在设计模式里--接口类

查看继承的方法:__base__   和  __bases__

__base__ : 只查看从左到右继承的第一个子类;

__bases__: 查看所有继承的父类;

# 查看子类继承了那些父类:__bases__
class A:pass
class B(object):pass
class A_son(A,B):pass
class B_son(B):pass
print(A_son.__bases__) # 查看继承了那个类
print(B_son.__bases__)
print(A.__bases__) # 默认继承object
# 在Python 3 中没有继承父类的,默认继承 object ---新式类
print(B.__bases__)

注意:如果一个类没有指定一个父类(基类或超类),那么默认继承一个叫object的类,object是所有Python类的父类(基类或超类),它提供了一些常用的方法(如:__str__的实现);在Python2.7里需要需添加object类才能成为新式类,否者就是经典类;在Python3中所有的类都是新式类;

# 例子
class Default_info:
    def __init__(self,name,age):
        self.name = name
        self.age = age

class Boy(Default_info):
    sex = '男'
    def msg(self):
        print('是一位男生')

class Girl(Default_info):
    sex = '女'
    def msg(self):
        print('是一位女生')

jerry = Boy('Jerry',18)
amy = Girl('Amy',18)
print(jerry.name)
print(amy.age)

继承与抽象

抽象即抽取类似或比较像的部分。

抽象分成两个层次:

1、将奥巴马和梅西这俩对象比较像的部分抽取成类;

2、将人,狗,猪这三个雷比较像的部分抽取成父类(基类或超类);

抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)

继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

class Animal:
    def animal_type(self):
        print('这是Animal类:',type(self))  # 运行后发现这里的self接收的是子类传过来的self
        print('%s的种类是:动物'%self)
        print('%s的种类是:动物'%self.name)

class Person(Animal):
    def username(self,name):
        print('这是Person类:',type(self))
        self.name = name
        print('人的名字是%s!'%name)

class Pig:
    def pigname(self,name):
        print('猪的名字是%s!'%name)

class Dog:
    def dogname(self,name):
        print('狗的名字是%s!'%name)

# 实例化
peole = Person()
peole1 = Person()
# 对象调用类的方法
peole.username('奥巴马')
peole1.username('梅西')
# 测试是否继承共有的属性
peole.animal_type()
peole1.animal_type()

继承与重用性

在开发过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同,如果类B再写一个和类A相同的东西,那么就造就了代码的累赘和重复,解决这个我们就用到了类的继承的概念。通过继承的方式新建类B,让B继承A,类B会'遗传'A的所有属性(数据属性和函数属性),实现代码的重用。

==========================第一部分
例如

  猫可以:吃、喝、爬树

  狗可以:吃、喝、看家

如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:


#猫和狗有大量相同的内容
class 猫:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 爬树(self):
        # do something



class 狗:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 看家(self):
        #do something


==========================第二部分
上述代码不难看出,吃、喝是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

  动物:吃、喝

     猫:爬树(猫继承动物的功能)

     狗:看家(狗继承动物的功能)

伪代码如下:
class 动物:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 猫(动物):

    def 爬树(self):
        print '喵喵叫'

# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 狗(动物):

    def 看家(self):
        print '汪汪叫'


==========================第三部分
#继承的代码实现
class Animal:

    def eat(self):
        print("%s 吃 " %self.name)

    def drink(self):
        print ("%s 喝 " %self.name)

class Cat(Animal):

    def __init__(self, name):
        self.name = name
        self.breed = '猫'

    def climb(self):
        print('爬树')

class Dog(Animal):

    def __init__(self, name):
        self.name = name
        self.breed='狗'

    def look_after_house(self):
        print('汪汪叫')


# ######### 执行 #########

c1 = Cat('小白家的小黑猫')
c1.eat()

c2 = Cat('小黑的小白猫')
c2.drink()

d1 = Dog('胖子家的小瘦狗')
d1.eat()

继承的重用性例子

注意:用已经有的类金莲一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大减轻了编程的工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的。比如标准库,来定制新的数据类型,这样就可以大大的缩减软件开发周期,对大型软件开发来说意义重大。

笔者自己有个疑问,什么时候适合在父类使用__init__,什么时候适合在子类中使用__init__,实例化,调用是否有差异?

# 例子:在一个人员信息里,人与人之间有同样属性的东西:名字,年龄,职位,以性别为区分
class All_info:
    def info(self,name,age,job):
        self.name = name
        self.age = age
        self.job = job
        print('''
        姓名:%s
        年龄:%s
        职位:%s
        '''%(name,age,job))

class Men(All_info):
    def sex(self):
        print('性别:男')

class Women(All_info):
    def sex(self):
        print('性别:女')

jerry = Men()
jerry.info('Jerry',18,'IT')
jerry.sex()

未使用__init__

# 例子:在一个人员信息里,人与人之间有同样属性的东西:名字,年龄,职位,以性别为区分

class All_info:
    def __init__(self,name,age,job):
        self.name = name
        self.age = age
        self.job = job
        print('''
        姓名:%s
        年龄:%s
        职位:%s
        '''%(name,age,job))

class Men(All_info):
    def sex(self):
        print('性别:男')

class Women(All_info):
    def sex(self):
        print('性别:女')

jerry = Men('Jerry',18,'IT')
jerry.sex()

使用__init__

派生

父类仲没有的属性,在子类仲出现,叫做派生属性
父类中没有的方法,在子类中出现,叫做派生方法
只要是子类的对象低啊用,子类中有的名字,一定用子类,子类中没有才找父类,如果父类也没有就报错
如果父类,子类都有,就一定用子类
如果还想用父类的,单独调用父类的,需要自己传self参数

#   父类名.方法名 需要自己传self参数
#   super().方法名 不需要自己传self
class Animal:
    '''
    人和狗都是动物,所以创造一个Animal基类
    '''
    def __init__(self, name, aggressivity, life_value):
        self.name = name  # 人和狗都有自己的昵称;
        self.aggressivity = aggressivity  # 人和狗都有自己的攻击力;
        self.life_value = life_value  # 人和狗都有自己的生命值;

    def eat(self):
        print('%s is eating'%self.name)

class Dog(Animal):
    '''
    狗类,继承Animal类
    '''
    def bite(self, people):
        '''
        派生:狗有咬人的技能
        :param people:
        '''
        people.life_value -= self.aggressivity

class Person(Animal):
    '''
    人类,继承Animal
    '''
    def attack(self, dog):
        '''
        派生:人有攻击的技能
        :param dog:
        '''
        dog.life_value -= self.aggressivity

egg = Person('egon',10,1000)
ha2 = Dog('二愣子',50,1000)
print(ha2.life_value)
print(egg.attack(ha2))
print(ha2.life_value)

注意:像ha2.life_value之类的属性引用,会先从实例中找life_value然后去类中找,然后再去父类中找...直到最顶级的父类。

 多继承

多继承:子类有多个父类

class A:
    def func(self):print('A')
class B:
    def func(self):print('B')
class C:
    def func(self):print('C')
class D(A,B,C):
    def func(self):print('D')

d = D()
d.func()

#情况1、注释D的方法
class A:
    def func(self):print('A')
class B:
    def func(self):print('B')
class C:
    def func(self):print('C')
class D(A,B,C):
    pass
    #def func(self):print('D')

d = D()
d.func()
#情况二、把A的方法注释
class A:
    pass
    # def func(self):print('A')
class B:
    def func(self):print('B')
class C:
    def func(self):print('C')
class D(A,B,C):
    pass
    # def func(self):print('D')

d = D()
d.func()

钻石继承

# python 3 中所有新式类 都是采用广度优先
class A:
    def func(self):print('A')
class B(A):
    pass
    #def func(self):print('B')
class C(A):
    pass
    #def func(self):print('C')
class D(B,C):
    pass
    #def func(self):print('D')

d = D()
d.func()
# 虽然遵守广度优先,但是也走深度优先
class A:
    def func(self):print('A')
class B(A):
    pass
    #def func(self):print('B')
class E:
    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()

菱形继承

class A:
    def func(self):print('A')
class F(A):
    pass
    # def func(self):print('F')
class B(F):
    pass
    #def func(self):print('B')
class E(A):
    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()

# mro() -- 记录继承的顺序
print(D.mro())

新式类的继承顺序:广度优先
Python2.7就有经典类:深度优先
多继承中,我们子类的对象低啊用一个方法,默认是就近原则,找的顺序是什么?
经典类中-->深度优先
新式类中-->广度优先
python2.7 新式类和经典类共存,新式类要继承object
python3 只有新式类,默认继承object
经典类和新式类的区别是
    super()只在python3中存在
    mro() 只在新式类中存在

super() 方法进阶

super的本质:不是直接找父类,而是根据调用者的节点位置的广度优先顺序来的。

class A:
    def func(self):print('A')
class B(A):
    def func(self):
        super().func()
        print('B')
class C(A):
    def func(self):
        super().func()
        print('C')
class D(B,C):
    def func(self):
        super().func()
        print('D')

d = D()
d.func()

class A:
    def func(self):print('A')
class B(A):
    def func(self):
        super().func()
        print('B')
class C(A):
    def func(self):
        super().func()
        print('C')
class D(B,C):
    def func(self):
        super().func()
        print('D')

b = B()
b.func()

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry's-Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值