python类方法继承_python的类的继承和多继承

一、类的继承

面向对象三要素之一,继承Inheritance

class Cat(Animal)这种形式就是从父类继承,继承可以让子类从父类获取特征(属性和方法)

在面向对象的世界中,从父类继承,就可以直接拥有父类的属性和方法,这样可以减少代码,多复用,子类可以定义自己的属性和方法

classAnimal:def __init__(self,name):

self._name=namedefshout(self):print('{} shout'.format(self.__class__.__name__))

@property#属性装饰器

defname(self):returnself._name

a= Animal('monster')

a.shout()classCat(Animal):passcat= Cat('garfield')

cat.shout()print(cat.name)

父类: Animal就是Cat的父类,也称为基类,超类

子类:Cat就是Animal的子类,也称为派生类

如果类定义时,没有基类列表,等同于继承自object,在python3中,object类是所有对象的根基类

1、查看继承的特殊属性和方法

__base__ : 类的基类

__based__ : 类的基类元组

__mro__ : 显示方法查找顺序,基类的元组

mro()方法 : 显示方法查找顺序,基类的元组

__subclasses__() : 类的子类列表

2、继承中的访问控制

从父类继承,自己没有的就可以到父类中找

私有的都是不可以访问的,但是本质上依然是改了名称放在这个属性所在类的__dict_-中

继承时,公有的,子类和实例都可以随意访问,私有成员被隐藏了,子类和实例不可直接访问

当私有变量所在的类内的方法中可以访问这个私有变量

属性查找属性:实例的dict--》类的dict--》父类dict

举例:classAnimal:__COUNT =0

HEIGHT=0def __init__(self,age,weight,height):

self.__COUNT += 1self.age=age

self.__weight =weight

self.HEIGHT=heightdefeat(self):print('{} eat'.format(self.__class__.__name__))def __getweight(self):print(self.__weight)

@classmethoddefshowcount1(cls):print(cls.__COUNT)

@classmethoddef __showcount2(cls):print(cls.__COUNT)classCat(Animal):

NAME= 'CAT'c= Cat(3,5,15)

c.eat()print(c.HEIGHT)#print(c.__COUNT) #私有的不可访问#c.__showweight() #私有的不可访问

c.showcount1()#c.__showcount2() #私有的不可访问

print(c.NAME)print("{}".format(Animal.__dict__))print("{}".format(Cat.__dict__))print(c.__dict__)print(c.__class__.mro())

3、方法的重写、覆盖overrride

classAnimal:defshout(self):print('Animal shout')classCat(Animal):#覆盖了父类方法

defshout(self):print('miao')#覆盖子类自身的方法,显示调用了父类的方法

defshout(self):print(super())print(super(Cat,self))

super().shout()

super(Cat,self).shout()

c=Cat()

c.shout()

4、继承中的初始化

classA:def __init__(self,a):

self.a=aclassB(A):def __init__(self,b,c):

self.b=b

self.c=cdefprintv(self):print(self.b)print(self.a) #报错

f= B(200,300)print(f.__dict__)print(f.__class__.__bases__)

f.printv()

上例代码可知:如果类B定义时声明继承自类A,则在类B中__bases__中是可以看到类A,但是这和是否调用类A的构造方法是两回事

1、如果子类B没有定义init方法,初始化的时候会自动调用基类A是init方法classA:def __init__(self):

self.a1= 'a1'self.__a2 = 'a2'

print('A init')classB(A):passb=B()print(b.__dict__)2、如果子类B定义了init方法,实例的初始化不会调用父类的初始化init方法classA:def __init__(self):

self.a1= 'a1'self.__a2 = 'a2'

print('A init')classB(A):def __init__(self):

self.b1= 'b1'

print('B init')

b=B()print(b.__dict__)3、通过上面分析,子类不会调用父类init方法,这导致没有实现继承效果,所以在子类的__init__方法中,

应该显式调用父类的__init__方法classAnimal:def __init__(self,age):print('Animal init')

self.age=agedefshow(self):print(self.age)classCat(Animal):def __init__(self,age,weight):#调用父类的__init__方法顺序决定着show方法的结果

super().__init__(age)print('Cat init')

self.age= age + 1self.weight=weight

c= Cat(10,5)

c.show()

注意、调用父类的__init__方法,出现在不同的位置,

二、多继承

OCP原则:多继承,少修改;继承的用途:增强基类,实现多

1、多态

在面向对象中,父类,子类通过继承联系在一起,如果可以通过一套方法,就可以实现不同的表现,就是多态

一个类继承自多个类就是多继承,它将具有多个类的特征

2、多继承弊端

多继承很好的模拟了世界,因为事物很少是单一继承,但是舍弃简单,必然引入复杂性带来冲突

如同一个孩纸继承了来自父母双方的特征

多继承的实现会导致编译器设计的复杂度增加,所以现在很多语言也舍弃了类的多继承

3、python多继承实现

多继承带来路径选择问题,究竟继承哪个父类的特征

python使用MRO(method resolution order)解决基类搜索顺序问题

4、多继承的缺点

当类很多,继承复杂的情况下,继承路径太多,很难说清楚什么样的继承路径

python语法是允许多继承,但是python代码是解释执行,只有执行到的时候才发现错误

举例:classPrintable:def_print(self):print(111,self.content)class Document: #第三方库,不允许修改

def __init__(self,content):

self.content=contentclass Word(Document): pass #第三方库,不允许修改

class Pdf(Document): pass #第三方库,不允许修改

class PrintableWord(Printable,Word): pass

print(222,PrintableWord.__dict__)print(333,PrintableWord.mro())

pw= PrintableWord('test string')

pw._print()

5、用装饰器增强

用装饰器增强一个类,把功能给类附加上去,哪个类需要,就装饰它

优点:简单方便,在需要的地方动态增加,直接使用装饰器

defprintable(cls):def_print(self):print(self.content,'装饰器')

cls.print =_printreturnclsclass Document: #第三方库,不允许修改

def __init__(self,content):

self.content=contentclass Word(Document): pass #第三方库,不允许修改

class Pdf(Document): pass #第三方库,不允许修改

@printable#先继承,后装饰

class PrintableWord(Word): pass

print(PrintableWord.__dict__)print(PrintableWord.mro())

pw= PrintableWord('test string')

pw.print()

6、Mixin的引用

Mixin本质上就是多继承实现的,是一种组合的设计模式

在面向对象的设计中,一个复杂的类往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多的类组合在一起

从设计的模式的角度来说,多组合,少继承

举例:classPrintableMixin:def print(self):print(self.content,'Mixin')defprintable(cls):def_print(self):print(self.content,'装饰器')

cls.print =_printreturnclsclass Document: #第三方库,不允许修改

def __init__(self,content):

self.content=contentclass Word(Document): pass #第三方库,不允许修改

class Pdf(Document): pass #第三方库,不允许修改

class PrintableWord(PrintableMixin,Word): pass

print(PrintableWord.__dict__)print(PrintableWord.mro())

pw= PrintableWord('test string')

pw.print()

Mixin就是其他类混合进来,同时带来了类的属性和方法,这里看来Mixin类和装饰器效果一样,也没有什么特别

但是Mixin是类,就可以继承

7、Mixin类的使用原则

Mixin类中不应该显式的出现__init__初始化方法

Mixin类通常不能独立工作,因为它是准备混入别的类中的部分功能实现

Mixin类的祖先类也应是Mixin类,使用时,Mixin类通常在继承列表的第一个位置

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值