python进阶(5):组合,继承

前两天我们认识了面向对象也对面向对象有了初步的认识今天我们先会说一点组合的进阶,今天重点是继承。

一、组合

组合只有一个例子因为组合只作为上一章的补充内容

#老师 课程 生日
class Course:
    def __init__(self,name,period,price):
        self.name = name
        self.period = period
        self.price = price

class Birth:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

class Teacher:
    def __init__(self,name,salary,boy_friend,python):
        self.name = name
        self.salary = salary
        self.bf = boy_friend
        self.course = python

python = Course(‘python‘,‘6 months‘,20000)

egg = Teacher(‘egon‘,200,‘yuan‘,python)
print(egg.bf)
print(egg.name)
print(egg.course.name)

egg_birth = Birth(1965,2,2)
print(egg_birth.year)
egg.birth = egg_birth
print(‘***‘,egg.birth.year)

组合



二、继承

1、何为继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

面向对象编程语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

继承

查询继承

SubClass1.__bases__ #查看所有继承的父类

如果没有指定基类,python的类会默认继承object类,object是所有python类的基类

2、继承与抽象

继承 是从大范围到小范围

抽象 小范围到大范围

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

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

3、继承与重用性

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):
    pass

class Person(Animal):
    pass

egg = Person(‘egon‘,10,1000)
ha2 = Dog(‘二愣子‘,50,1000)
egg.eat()
ha2.eat()

代码重用

用已经有的类建立一个新的类,这样就重用了已经有的类中的一部分甚至大部分,大大节省了编程工作量,这就是重用

4、派生

当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

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然后去类中找,然后再去父类中找...直到最顶级的父类。

子类执行父类的方法可以直接用super方法,或者用调用普通函数的方式,即:类名.func()

class Animal:      #父类  基类  超类
    def __init__(self,name,life_value,aggr):
        self.name = name
        self.life_value = life_value
        self.aggr = aggr  #攻击力
    def eat(self):
        self.life_value += 10

class Person(Animal):  #子类  派生类
    def __init__(self,money,name,life_value,aggr):
        super().__init__(name,life_value,aggr)
        self.money = money   #派生属性

    def attack(self,enemy):    #人的派生方法
        enemy.life_value -= self.aggr

class Dog(Animal): #子类  派生类
    def __init__(self,breed,name,life_value,aggr):
        #Animal.__init__(self,name,life_value,aggr)   #让子类执行父类的方法,就是父类名.方法名(参数),连self也得传
        super().__init__(name,life_value,aggr)  #super关键字——新式类
        #super(Dog,self).__init__(name,life_value,aggr)  #super关键字——新式类
        self.breed = breed
    def bite(self,person):   #狗的派生方法
        person.life_value -= self.aggr

    def eat(self):       # 父类方法的重写
        super().eat()
        print(‘dog is eating~~~ ‘)

ha2 = Dog(‘牛头梗‘,‘旺财‘,20000,100)
print(ha2.life_value)
ha2.eat()
print(ha2.life_value)
# super(Dog,ha2).eat()  #调用父类的
print(ha2.life_value)

super

5、小结

在继承中
继承的语法:
class 类名(父类名):
想在子类中实现调用父类的方法
    在类内 ——super(子类名,self).方法名()
    在类外面 ——super(子类名,对象名).方法名()
如果不指定继承的父类,默认继承object
子类可以使用父类的所有属性和方法
    如果子类有自己的方法就执行自己的的
    如果是子类没有的方法就执行父类的
    如果子类父类都没有这个方法就报错

继承、抽象、派生
继承 是从大范围到小范围
抽象 小范围到大范围
派生 就是在父类的基础上又产生子类——派生类
        父类里没有的 但子类有的 ——派生方法,派生属性
方法的重写
    父类里有的方法,在子类里重新实现

小结



三、抽象类与接口类

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

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

在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。

1、多继承问题

在继承抽象类的过程中,我们应该尽量避免多继承;

而在继承接口的时候,我们反而鼓励你来多继承接口

接口隔离原则:
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

2、方法的实现

1)在抽象类中,我们可以对一些抽象方法做出基础实现;

from abc import ABCMeta,abstractmethod
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        print(‘打开粮食的袋子‘)
        print(‘放一个吃饭的碗‘)
        print(‘把粮食倒在碗里‘)

    @abstractmethod
    def sleep(self):
        pass

class Dog(Animal):
    def eat(self):
        super().eat()
        print(‘dog is eating‘)

    def sleep(self):
        print(‘dog is sleeping‘)

d = Dog()
d.eat()

抽象类

抽象类:

抽象: 从小范围到大范围

2)而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现

from abc import ABCMeta,abstractmethod
class Payment(metaclass = ABCMeta):  #metaclass --> 元类
    @abstractmethod
    def pay(self,money):pass

class Applepay(Payment):
    def pay(self,money):
        print(‘apple pay 支付了%s‘%money)

class Alipay(Payment):
    def pay(self,money):
        print(‘支付宝 支付了%s‘%money)

class Wechatpay(Payment):
    def fuqian(self,money):
        print(‘微信支付了%s‘%money)

def payment(pay_obj,money):
    pay_obj.pay(money)

apple1 = Applepay()
ali1 = Alipay()
wechat1 = Wechatpay()
payment(wechat1,200)

接口类

接口类:

约束继承接口类的子类必须实现被abstractmethod装饰的方法

在接口类中不要做实现(不要出现函数体)

接口类不能被实例化

3、小结

1)当几个子类的父类 有相同的功能需要被实现的时候 就用抽象类

当几个子类 有相同的功能 但是实现各不相同的时候 就用接口类

抽象类和接口类的本质作用:约束

2)抽象类

在Python里 默认是有的

父类的方法 子类必须实现

抽象类 不能被实例化

抽象类内的方法 可以被简单实现

3)接口类(在抽象类的基础上)

在python里 默认是没有的

接口类中的方法 不能被实现

原则:抽象类最好不要用多继承,而接口类可以



四、钻石继承

继承顺序

python如果继承了多个类寻找方法有两个方法深度优先(经典类)和广度优先(新式类),而python3中没有经典类了,所以我们不用考虑多重情况。

class A(object):
    def test(self):
        print(‘from A‘)

class B(A):
    def test(self):
        print(‘from B‘)

class C(A):
    def test(self):
        print(‘from C‘)

class D(B):
    def test(self):
        print(‘from D‘)

class E(C):
    def test(self):
        print(‘from E‘)

class F(D,E):
    # def test(self):
    #     print(‘from F‘)
    pass
print(F.mro())
 #这个属性可以查看继承属性

#新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C
#python3中统一都是新式类
#pyhon2中才分新式类与经典类

继承顺序

上面这个图这是让大家了解一下,平时可以直接使用mro()方法查看

时间: 2024-10-16 07:12:56

python进阶(5):组合,继承的相关文章

Python进阶-----类组合的方式完成授权

授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能.其它的则保持原样.授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性. import time class FileHandle: def __init__(self,filename,mode = 'r',encoding = 'utf-8'): self.file = open(filename,mode,encoding=encod

Python进阶-继承中的MRO与super

摘要本文讲述Python继承关系中如何通过super()调用"父类"方法,super(Type, CurrentClass)返回CurrentClass的MRO中Type的下一个类的代理:以及如何设计Python类以便正确初始化. 1. 单继承中父类方法调用 在继承中,调用父类方法是很有必要的.调用父类方法的场景有很多: 比如必须调用父类的构造方法__init__才能正确初始化父类实例属性,使得子类实例对象能够继承到父类实例对象的实例属性: 再如需要重写父类方法时,有时候没有必要完全摒

Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)

Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装: ? ? ? ? ? ?将一些东西封装到一个地方,你还可以取出来 ? ? ? ? ? ?类设置静态属性, 设置一些方法 或者 对象, 对象可以在其对象封装一些属性 多态: ? ? ? ? ? ?python默认支持多态, 多态指的是一种事务具有多种形态 ? ? ? ? ? ?1.多态可以增加代码的灵活度: ? ? ? ? ? ?2.以继承和重写父类方法为前提: ?

C++进阶--代码复用 继承vs组合

//############################################################################ /* * 代码复用: 继承 vs 组合 */ //继承实现代码复用 class BaseDog { ... ... // 公共的操作 }; class BullDog : public BaseDog { ... // 调用公共操作,执行更多任务 }; class ShepherdDog : public BaseDog { ... //

python进阶强化学习

最近学习了慕课的python进阶强化训练,将学习的内容记录到这里,同时也增加了很多相关知识. 主要分为以下九个模块: 基本使用 迭代器和生成器 字符串 文件IO操作 自定义类和类的继承 函数装饰器和类的装饰器 进程和线程 内存管理和垃圾回收机制 基本使用 基本的数据包括:list,tuple(元组),set(集合)和dict(字典).heapq.queue 处理的实际问题是:过滤列表中的负数 解决方案: 列表解析,最好的方式 字典,使用字典的方式和使用列表的方式差不多,都是对value做判断,但

python进阶十_正则表达式(一)

最近状态一直不太好,至于原因,怎么说呢,不好说,总之就是纠结中覆盖着纠结,心思完全不在点上,希望可以借助Python的学习以及博客的撰写来调整回来,有的时候回头想一想,如果真的是我自己的问题呢,以前我经常跟别人说,千万不要怀疑自己,因为很清楚一旦连自己都变的不可信,那这个世界就太疯狂了,当一遍一遍的问我,现在连我自己都快怀疑自己了,我一遍一遍的说服别人,想不到现在竟然需要自己去说服自己,何其的悲哀~ 一.正则表达式基础 1.基本概念 正则表达式是计算机科学的一个概念.正则表达式使用单个字符串来描

Python进阶(三十四)-Python3多线程解读

Python进阶(三十四)-Python3多线程解读 线程讲解 ??多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度. 程序的运行速度可能加快. 在一些等待的任务实现上如用户输入.文件读写和网络收发数据等,线程就比较有用了.在这种情况下我们可以释放一些珍贵的资源如内存占用等等. ??线程在执行过程中与进程还是有区别的.每个独立

Python进阶 函数式编程和面向对象编程等

函数式编程 函数:function 函数式:functional,一种编程范式.函数式编程是一种抽象计算机的编程模式. 函数!= 函数式(如计算!=计算机) 如下是不同语言的抽象 层次不同 高阶函数:能接收函数做参数的函数 变量可以指向函数 函数的参数可以接收变量 一个函数可以接收另一个函数作为参数 例子: 接收abs函数, 定义一个函数,接收x,y,z三个参数.其中x,y是数值,z是函数 . 1 2 3 def add(x,y,z):     return z(x)+z(y) print ad

Python进阶(三十六)-Web框架Django项目搭建全过程

Python进阶(三十六)-Web框架Django项目搭建全过程 ??IDE说明: Win7系统 Python:3.5 Django:1.10 Pymysql:0.7.10 Mysql:5.5 ??Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站! Django 特点 强大的数据库功能 用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句. 自带的强大的后台功能 几行简单的代码就让你的网

一、Python 进阶 之 函数式编程

Python 进阶 之 函数式编程 写在前面 入门阶段的系列笔记传送门 → 进这里 已经掌握了基础的内容如下: 变量和数据类型:Python 内置的基本类型 List 和 Tuple:顺序的集合类型 条件判断和循环:控制程序流程 Dict 和 Set:根据Key访问的集合类型 函数:定义和调用函数 切片:如何对 list 进行切片 迭代:如何用 for 循环迭代集合类型 列表生成式:如何快速生成列表 接下来我要学会: 函数式编程 如何使用 Python 的模块(内置模块和第三方模块) 面向对象编