python3 类的继承 supper_python3 继承,接口继承,抽象类,super调用父类的方法,多态...

任性插入:

继承的时候,如果子类中没有初始化函数,但是要去看看父类中有没有初始化函数,再决定子类在实例化的时候要不要传参;

子类中的方法想要调用父类中的方法,self.方法名;

子类中的方法想使用类中的其他方法也是加上self.;

1.面向对象三大特性:

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中;

继承 实现代码的重用,相同的代码不需要重复的编写;

多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度;

补充:

【转自别人】

继承好处:

提升代码的重用率:

有利于代码的管理,在需要改代码的时候,只需要在父类中修改,不需要动子类中的代码。

单继承和多继承(但是在java中继承只能是单继承,其余的语言不清楚)

classFather():pass

classMather():pass

class Son(Father):##########单继承

pass

class Daughter(Father,Mather):##########多继承

pass

View Code

2.什么时候用组合,什么时候用继承?

(1)当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好;

比如说一架车子是由不同的组件组合起来的,这样类似的即用组合,把全部的零件组装成一个完整的整体。

(2)当类之间有很多相同的功能,把这些共同的功能写成父类,子类去继承就可以,用继承比较好;

比如小猫小狗人都有吃喝拉睡的动作,如果在各自的类中都要写吃喝拉睡的方法,那重复的代码太多,那就可以使用继承,写个动物类中有吃喝拉睡,小猫小狗人调用即可。

3.继承的作用:

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

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

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

【copy来的:接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,

可一视同仁的处理实现了特定接口的所有对象”一这在程序设计上, 叫做归一化。】————个人感觉意思就是:任何一个子类要调用接口类都必须要实现其定义的方法,

子类想怎么实现就怎么实现,不关其他任何人的事情,当然子类还可以有属于自己的方法【类似java中的接口。。。。】。

4.继承的MRO顺序:

在经典类中,没有继承object类

在新式类中,有继承object类

在python3中,所有类最顶层父类都是object类,与java类似,如果定义类的时候没有写出父类,则object类就是其直接父类。

现在的问题是,如果多个父类中包含了同名的方法,此时会发生什么呢?此时排在前面的父类中的方法会“遮蔽”排在后面的父类中的同名方法。

class Father(object):#######新式类

pass

class Mather():##########经典类

pass

View Code

但是,这一切在python3出现之后发生了变化,因为在python3里面创建的都是新式类。

不管它俩的变化,我们目前关注的是两种类在多继承状态下查找“方法”的顺序。

经典类:深度查找

新式类:广度查找

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

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

但是在新式类中,对于程序猿定义的每一个类,python会计 算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表

为了实现继承.python会在MRO列表上从左到右开始查找基类,当到找到第一个匹配这个属生的类为止,

而这个MRO列表的构造是通过一个C3线性化算法来实现的。它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

(1)子类会先于父类被检查【类似作用域】

(2)多个父类会根据它们在列表中的顺序被检查

(3)如果对下一个类存在两个合法的选择,选择第一个父类;

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

classFather():print("这个是父亲")classMather():print("这个是母亲")class Son(Father):##########单继承

print("这个是儿子")class Son1(Father,Mather):##########多继承

print("这个是儿子")class Daughter(Father,Mather):##########多继承

print("这个是女儿")print(Son1.__mro__)print(Daughter.__mro__)###################

这个是父亲

这个是母亲

这个是儿子

这个是儿子

这个是女儿

(, , , )

(, , , )

View Code

重写:

子类包含与父类同名的方法的现象被称为方法重写(Override),也被称为方法覆盖。可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。

通过使用未绑定方法即可在子类中再次调用父类中被重写的方法

【在通过类名调用实例方法时,Python 不会为实例方法的第一个参数 self 自动绑定参数值,而是需要程序显式绑定第一个参数 self。这种机制被称为未绑定方法。】

classFruit():defname(self):print('我是所有水果的父类')classApple(Fruit):defname(self):print('我重写了Fruit的name方法——苹果')defrun_fruit(self):#直接执行name方法,将会掉哟个子类重写之后的name方法

self.name()#使用类名调用实例方法(未绑定方法)调用父类被重写的方法

Fruit.name(self)

apple=Apple()

apple.name()

apple.run_fruit()##########################

我重写了Fruit的name方法——苹果

我重写了Fruit的name方法——苹果

我是所有水果的父类

View Code

5.接口继承

接口是一组功能的入口,要调用某一组功能,需要通过接口来进行调用,而不需要关注这组功能是如何实现的,要的只是结果。

在类里,接口是提取了一群类共同的函数,可以把接口当做一个函数的集合。

正如2所说的,接口父类只是定义有什么方法,但是并不具体实现其方法体,当有子类去继承该父类时候,需要具体去实现这些方法体。

1 classAnimal():2 defeat(self):3 pass

4 defread(self):5 pass

6

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

11 defread(self,name):12 print('%s 在读书' %name)13 a=Animal()14 print(a.eat())15 c=Cat()16 c.eat("周周")17 c.eat("小周周")18

19 ############

20

21 None22 周周 在吃鱼23 小周周 在吃鱼

View Code

6.抽象类

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

抽象类介于接口和归一化中间,用于实现接口的归一化

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

1、子类必须要有父类的方法

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

python的抽象类通过abc模块实现。

importabcclass Animal(metaclass=abc.ABCMeta):

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

classCat(Animal):defeat(self,name):print('%s 在吃鱼' %name)defread(self,name):print('%s 在读书' %name)###a=Animal()#####注意注意,不能实例化,否则报错#####TypeError: Can't instantiate abstract class Animal with abstract methods eat, read

c=Cat()

c.eat("周周")

c.eat("小周周")######

周周 在吃鱼

小周周 在吃鱼

View Code

7.super方法调用父类的数据属性和函数属性

Python 要求,如果子类重写了父类的构造方法,那么子类的构造方法必须调用父类的构造方法。

子类的构造方法调用父类的构造方法有两种方式:

使用未绑定方法,这种方式很容易理解。因为构造方法也是实例方法,当然可以通过这种方式来调用。

使用 super() 函数调用父类的构造方法。

【注意,当子类继承多个父类是,super() 函数只能用来调用第一个父类的构造方法,而其它父类的构造方法只能使用未绑定的方式调用。】

在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用,使用super().__init__()或parentClassName.__init__()或者其他方式。【书写的方式有点点不同】

重写了就只会调用子类中的重写的方法;

'''重写:子类和父类里面有相同的函数名

扩展:子类有父类里面没有的方法'''

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

self.name=name

self.age=agedefmsg(self):print('我是父类!!!!')classSon(Parent):def __init__(self,name,age,job):

super().__init__(name,age)

self.job=jobdefmsg(self):print('我是子类============')defjob_msg(self):print('我的名字是:{0},年龄{1},工作是:{2}'.format(self.name,self.age,self.job))

son=Son('jack','25','python测试工程师')

son.msg()

son.job_msg()##########################

我是子类============我的名字是:jack,年龄25,工作是:python测试工程师

View Code

classVehicle1:

Country='China'

def __init__(self,name,speed,load,power):

self.name=name

self.speed=speed

self.load=load

self.power=powerdefrun(self):print('开动啦')print('开动啦')classSubway(Vehicle1):def __init__(self,name,speed,load,power,line):###使用父类的数据属性

#Vehicle.__init__(self,name,speed,load,power)###如果是使用父类的名字,那在修改后,子类的就很麻烦修改

super().__init__(name,speed,load,power)###super就不用修改咯

#super(__class__,self).__init__(name,speed,load,power)###三种方式均可以

#super(Subway,self).__init__(name,speed,load,power)

self.line=linedefshow_info(self):print(self.name,self.speed,self.load,self.power,self.line)defrun(self):###调用父类的方法

#Vehicle.run(self)

super().run()print('%s %s 号线,开动啦' %(self.name,self.line))

line2=Subway('成都地铁','100km/h',1000000000,'电',2)

line2.show_info()

line2.run()print(line13.__class__)########

成都地铁 100km/h 1000000000 电 2开动啦

成都地铁2号线,开动啦

View Code

super()是一个特殊的函数,将父类跟子类关联起来,super()._init_(),,其作用是将子类包含父类的所有属性。

【为避免多继承报错,使用不定长参数,接受参数】

__author__ = 'Administrator'

classParent(object):def __init__(self,name):print("Parent的__init__方法开始!!调用")

self.name=nameprint("Parent的__init__方法结束==调用")classSon1(Parent):def __init__(self,name,age):print("Son1的__init__方法开始调用")

self.age=age

Parent.__init__(self,name)print("Son1的__init__方法结束调用")classSon2(Parent):def __init__(self,name,gender):print("Son2的__init__方法开始调用")

self.gender=gender

Parent.__init__(self,name)print("Son2的__init__方法结束调用")classGrandson(Son1,Son2):def __init__(self,name,age,gender):print("Grandson的__init__方法开始调用")

Son1.__init__(self,name,age)

Son2.__init__(self,name,gender)print("Grandson的__init__方法结束调用")

grandson=Grandson("孙子",18,"男")############################

Grandson的__init__方法开始调用

Son1的__init__方法开始调用

Parent的__init__方法开始!!调用

Parent的__init__方法结束==调用

Son1的__init__方法结束调用

Son2的__init__方法开始调用

Parent的__init__方法开始!!调用

Parent的__init__方法结束==调用

Son2的__init__方法结束调用

Grandson的__init__方法结束调用

View Code

___author__ = 'Administrator'

classParent(object):def __init__(self,name,*args,**kargs):print("Parent的__init__方法开始!!调用")

self.name=nameprint("Parent的__init__方法结束==调用")classSon1(Parent):def __init__(self,name,age,*args,**kargs):print("Son1的__init__方法开始调用")

self.age=age

super().__init__(name,*args,**kargs)print("Son1的__init__方法结束调用")classSon2(Parent):def __init__(self,name,gender,*args,**kargs):print("Son2的__init__方法开始调用")

self.gender=gender

super().__init__(self,name,*args,**kargs)print("Son2的__init__方法结束调用")classGrandson(Son1,Son2):def __init__(self,name,age,gender):print("Grandson的__init__方法开始调用")

super().__init__(name,age,gender)print("Grandson的__init__方法结束调用")

grandson=Grandson("孙子",18,"男")##############################

Grandson的__init__方法开始调用

Son1的__init__方法开始调用

Son2的__init__方法开始调用

Parent的__init__方法开始!!调用

Parent的__init__方法结束==调用

Son2的__init__方法结束调用

Son1的__init__方法结束调用

Grandson的__init__方法结束调用

View Code

___author__ = 'Administrator'

classParent(object):def __init__(self,name,*args,**kargs):print("Parent的__init__方法开始!!调用")

self.name=nameprint("Parent的__init__方法结束==调用")classSon1(Parent):def __init__(self,name,age,*args,**kargs):print("Son1的__init__方法开始调用")

self.age=age

super().__init__(name,*args,**kargs)print("Son1的__init__方法结束调用")classSon2(Parent):def __init__(self,name,gender,*args,**kargs):print("Son2的__init__方法开始调用")

self.gender=gender

super().__init__(self,name,*args,**kargs)print("Son2的__init__方法结束调用")classGrandson(Son1,Son2):def __init__(self,name,age,gender):print("Grandson的__init__方法开始调用")

super().__init__(name,age,gender)print("Grandson的__init__方法结束调用")print(Grandson.__mro__)

grandson=Grandson("孙子",18,"男")#################################

(, , , , )

Grandson的__init__方法开始调用

Son1的__init__方法开始调用

Son2的__init__方法开始调用

Parent的__init__方法开始!!调用

Parent的__init__方法结束==调用

Son2的__init__方法结束调用

Son1的__init__方法结束调用

Grandson的__init__方法结束调用

View Code

通过父类名调用的时候,parent调用了两次;

使用super的时候,parent 只是执行了一次;

___author__ = 'Administrator'

classParent(object):def __init__(self,name):print("Parent的__init__方法开始!!调用")

self.name=nameprint("Parent的__init__方法结束==调用")classSon(Parent):def __init__(self,name,age):print("Son的__init__方法开始调用")

self.age=age

super().__init__(name)#单继承不能提供全部参数

print("Son的__init__方法结束调用")classGrandson(Son):def __init__(self,name,age,gender):print("Grandson的__init__方法开始调用")

super().__init__(name,age)#单继承不能提供全部参数

print("Grandson的__init__方法结束调用")

grandson=Grandson("孙子",18,"男")###########################

Grandson的__init__方法开始调用

Son的__init__方法开始调用

Parent的__init__方法开始!!调用

Parent的__init__方法结束==调用

Son的__init__方法结束调用

Grandson的__init__方法结束调用

View Code

【转自别人:】

总结:

super().__init__相对于类名.__init__,在单继承上用法基本无差;

但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果;

多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错;

单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错,

多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因。

不知道是不是重复了:具有两个父类的属性和方法,如果两个父类具有同名方法的时候,就近原则(__init__也是)。

8.

在调用父类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数;

重写父类方法——————————对于父类的方法,如果有不符合子类想要做的事情,可以对父类的方法进行重写,重写时要与父类的方法同名,这样python将不会考虑父类的方法,而只是关注子类定义的相应的方法。

9.

isinstance(obj,cls)判断是否obj是否是类 cls 的对象

issubclass(sub, super)判断sub类是否是 super 类的派生类

1 classPerson():2 pass

3 classMan(Person):4 pass

5 p=Person()6 m=Man()7 print(isinstance(p,Person))8 print(isinstance(m,Person))#####因为有了继承的关系

9 print(isinstance(p,Man))10 print(issubclass(Man,Person))11

12 ######################

13True14True15False16 True

View Code

10.多态:同一个方法在不同的类中最终呈现出不同的效果,即为多态。

classFruit():defname(self):print('我是水果')classApple(Fruit):defname(self):print('我是苹果')

Fruit().name()

Apple().name()

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值