python组合和继承_python3基础-组合和继承

组合

软件重用的重要方式除了继承之外还有另外一种方式,即:组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

classschool:def __init__(self,name,addr):

self.name=name

self.addr=addrdeftype(self):print("%s 是 公立学校"%self.name)classstudent:'学生的信息'empcount=0def __init__(self,name,sex,age,school):

self.name=name

self.sex=sex

self.age=age

self.school=schooldeftype(self):

self.school.type()#通过对象去调用type函数

print('哈哈哈哈哈')

stu1=student('susu','未知',18,school('北大','北京'))print(stu1.__dict__)print(stu1.name)print(stu1.school.name)print(stu1.school.addr)

stu1.type()

继承

继承是一种创建新类的方式

在python中,新建的类可以继承一个或多个父类,新建的类可称为子类或派生类,父类又可以称为基类或超类

class Parent1: #定义父类 基类 超类

pass

class Parent2: #定义父类 基类 超类

pass

class Subclass1(Parent1):#单继承 子类 派生类

pass

class Subclass2(Parent1,Parentc2):#多继承 子类 派生类

pass

#类的内置属性__bases__可以查看类继承的所有父类

print(Subclass2.__bases__)print(Subclass1.__bases__)

(, )

(,)

继承顺序之MRO线性顺序

经典类:没有显示地继承object类的类,以及该类的子类,都是经典类==》深度查找

新式类:显示地继承object类的类,以及该类的子类,都是新式类==》广度查找

经典类顺序(深度):F--D--B--A 后F --E--C--A

新式类顺序(广度): F--D--B (不找基类)后 F--E--C--A

新式类可以直接通过 类名.__mro__的方式取类的MRO,也可以通过类目.mro()的形式

classA:pass

classB:pass

classC(A,B):pass

print(C.__mro__)print(C.mro())

”“”

执行结果

(, , , )

[, , , ]

“”“

在python3中都是同样的新式类,即使没有显示的继承object,也会默认继承该类

print(Parent1.__bases__) #输出 (,)

print(Parent2.__bases__) #输出 (,)

实例

classPeople:'''定义一个人类,

姓名、性别、年龄'''

def __init__(self,name,sex,age):

self.name=name

self.sex=sex

self.age=ageclassStudent(People):'''定义一个学生类'''

defstudying(self):print('%s is studying'%self.name)classTeacher(People):'''定义一个老师类'''

defteach(self):print('%s is teaching'%self.name)

直接调用Teacher()

teacher1=Teacher()#未传入参数,则会报错TypeError: __init__() missing 3 required positional arguments: 'name', 'sex', and 'age'

Teacher类并没有定义__init__方法,但是会从父类中找到__init__则

teacher1=Teacher('苏苏','未知',20)print(teacher1.school,teacher1.name)

teacher1.teach()#=============

"""执行结果如下

福大 苏苏

苏苏 is teaching"""

总结:因为有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找

继承-子类和父类的数据属性重名的问题

classPeople:'''定义一个人类,

姓名、性别、年龄'''school= '福大'

def __init__(self,name,sex,age):

self.name=name

self.sex=sex

self.age=ageclassStudent(People):'''定义一个学生类'''

defstudying(self):print('%s is studying'%self.name)classTeacher(People):'''定义一个老师类'''school= '北大' #子类自定义的属性和父类People的属性重名

defteach(self):print('%s is teaching'%self.name)

teacher1= Teacher('susu','未知',50)print(teacher1.school) #输出子类的 school为北大

print(People.school) #输出父类的 school 为福大 ;并不会被子类覆盖

派生与方法重用

父类中没有的属性 子类中出现 叫派生属性

父类中没有的方法 子类中出现 叫派生方法

父类和子类都有 调用子类 想调用父类的药指出父类名称调用

每个老师还有职称这个属性,则就需要在Teacher类中定义该类自己的__init__

classPeople:

school= '福大'

def __init__(self,name,sex,age):

self.name=name

self.sex=sex

self.age=ageclassStudent(People):defstudying(self):print('%s is studying'%self.name)classTeacher(People):def __init__(self,name,sex,age,titles):

self.name=name #重复代码

self.sex=sex #重复代码

self.age=age #重复代码

self.titles=titlesdefteach(self):print('%s is teaching'%self.name)

teacher1= Teacher('susu','女',29,'高级讲师') #只会找Teacher类中的__init__,并不会自动调用父类的

print(teacher1.name,teacher1.sex,teacher1.age,teacher1.titles)#输出的是susu 女 29 高级讲师

若想在子类派生的方法内重用父类的功能

1、直接调用某一个类的函数

classTeacher(People):def __init__(self, name, sex, age, titles):

People.__init__(self,name,sex,age) #调用的是函数,因而需要传入self

self.titles =titlesdefteach(self):print('%s is teaching'%self.name)

2、super()

调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照MRO规定的顺序向后查找

classTeacher(People):def __init__(self, name, sex, age, titles):

super().__init__(name,sex,age) #调用的是绑定方法,自动传入self

self.titles =titlesdefteach(self):print('%s is teaching'%self.name)

组合和继承区别

1、当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好2、当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好

继承的作用

(1)减少重复代码,子类可扩展或者可以修改【但是往往在实践中,该含义意义并不很大,甚至常常是有害的,因为它使得子类与基类出现强耦合。】

(2)声明某个子类兼容于某基类,定义一个接口类,子类继承接口类,并且在子类实现接口中定义的方法————————————接口继承

【目的:规范子类,子类实现接口类的中定义的方法,并且不必要实例化】

【接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,一视同仁的处理实现了特定接口的所有对象”一这在程序设计上, 叫做归一化。】

抽象类

抽象类的本质上也是类,但是抽象类只能够被继承,不能进行实例化,也就是说可以当父类,但是不能生成对象。

当子类继承抽象类的时候,如果抽象类定义了抽象方法,那么子类必须要定义同名的方法,即父类限制:

1、子类必须要有父类的方法2、子类实现的方法必须跟父类的方法的名字一样

importabcclass Animal(metaclass=abc.ABCMeta):

@abc.abstractmethoddefeat(self):pass@abc.abstractmethoddefaction(self):pass

classCat(Animal):defeat(self,name):print('%s 在吃鱼' %name)

cat1=Cat()#会报错TypeError: Can't instantiate abstract class Cat with abstract methods action#因为子类Cat 没有和父类的方法一样,缺失一个action方法

importabcclass Animal(metaclass=abc.ABCMeta):

@abc.abstractmethoddefeat(self):pass@abc.abstractmethoddefaction(self):pass

classCat(Animal):defeat(self,name):print('%s 在吃鱼' %name)defaction(self,name):print('%s 在喵喵叫' %name)#ani = Animal()#不能进行实例化,会报错TypeError: Can't instantiate abstract class Animal with abstract methods action, eat

cat1=Cat()

cat1.eat('小黑猫')

cat1.action('小黑猫')

”“”

小黑猫 在吃鱼

小黑猫 在喵喵叫

“”“

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值