继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
类继承实现了重用代码,方便代码的管理和修改。
继承
类继承的写法
class Father(object): #其中object是父类
pass
fa = Father() # 会调用父类的__init__方法,这就是继承
当一个类继承自另一个类时,会先去自雷查找对应的方法或属性,如果有,则优先调用子类的属性和方法,如果没有,则会去父类查找对应的属性或方法。
#简单的继承示例
class Rectangle: #父类
def __init__(self,width,height):
self.width = width
self.height = height
def get_Area():
area = self.width*self.height
return area
#子类继承父类
class Square(Rectangle):
pass
def my_func(): #子类自己的方法,父类中没有
pass
其中子类Square全面继承了父类Rectangle的所有内容,同时类Square还可以写自己的方法。
重用父类的init方法:
class Square(Rectangle):
def __init__(self,width,height):
if width==height:
Rectangle.__init__(self,width,height)
#正方形类继承自长方形类,如果边长相等,就直接调用父类的init方法实行初始化,实现了父类的init方法重用
def my_func(): #子类自己的方法,父类中没有
pass
如果上述的初始化未能执行完成(即if条件不成立),那么Square类会没有对应的self.width和self.height的类属性。
访问类的属性或方法:
- 首先会在类本身找
- 如果找不到转到其父类中查找,即直接基类中查找
- 如果再找不到转到其父类的父类中查找,即间接基类中查找
顶级父类
object关键字
object是所有类的父类,即相当于所有类的祖宗,是所有类最顶层的基类。
通过__bases__方法可以查找对应类的父类。
#查找Square类的基类
Square.__bases__
#结果是 (<class '__main__.Rectangle'>,)
#查找Rectangle类的基类
Rectangle.__bases__
#结果是(<class 'object'>,)
多继承
一个类可以继承一个类,继承之后可以使用父类的方法和属性,如果一个类继承自多个类,那么成为多继承。
一个多继承示例
#基类
class Base:
def play(self):
print('这是Base')
#继承基类base
class A(Base):
def play(self):
print('这是A')
#继承基类base
class B(Base):
def play(self):
print('这是B')
#继承父类A,B,子类C就是多继承
class C(A, B):
pass
图示
通过C类实例的方法调用来看
当继承多个父类时,如果父类中有相同的方法,
那么子类会优先使用最先被继承的方法
优先级是从左往右,即C类会有优先调用A类中的方法,再次B类 ,如果A类和B类都没有找到对应的方法,会继续从base中找对应的方法。
如果想在子类中调用父类的方法没可以如下写法:
class A:
def func(self):
pass
class B(A):
def func(self):
A.func(self) #这里调用了父类A的方法
但是对于多继承,往往我们无法确定调用哪个父类的方法,所以需要用到super方法,所以上述的方式可以如下写法:
class A:
def func(self):
pass
class B(A):
def func(self):
super().func(self) #这里调用了父类A的方法
super().func(self)会直接使用A的方法(优先使用A的,如果A没有,再次找B类的方法)
如果有多层继承,可以使用mro方法来查看继承关系。
#如下
B.mro() #可以查看B类的继承关系
通过多继承可以将多个类的方法拼接到一个类来使用,为Min-in模式。
常用的魔法方法
__add__(self,other) #可以实现类的相加
__sub__(self,other) #减法
__mul__(self,other) #乘法
__mod__(self,other) #除法
#加法的示例
class A:
def __add__(self,other): #other表示其他的类
add_length = self.length+other.length
return add_length
还有些特殊的方法,可以便于使用者调试。
def __str__(self):
return 内容
#如果定义了str方法,当执行打印实例名的时候,打印的实际是str的返回值
str方法对使用者友好,返回的是字符串,返回结果可读性强,方便使用者阅读。
def __repr__(self):
return 内容
#如果定义了repr方法,执行打印实例名,打印的是repr的返回值,如果str和repr都定义了,那么执行打印的时候会只打印str返回的内容
repr开发者调试友好,返回字符串,返回的结果更加精确,方便开发人员使用
当使用%s占位符打印实例化对象的时候,会调用str方法
当使用%r占位符打印实例化对象的时候,会调用repr方法
交互模式下嗲用的就是repr来显示返回的内容
def __call__(self,*args,**kwargs):
pass
#实例化对象后加一个()可以调用call方法
call方法可以通过实例化对象来直接调用,调用方法就是实例化对象名字后加一个括号()
综合运用示例
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
# 求面积
def get_Area(self):
area = self.width * self.height
return area
# 求周长
def get_Perimeter(self):
perimeter = (self.width + self.height) * 2
return perimeter
# 正方形
class Square(Rectangle):
def __init__(self, width, height):
if width == height:
Rectangle.__init__(self, width, height)
else:
print('边长不相等,这不是正方形!')
def __call__(self, *args, **kwargs):
print('正方形的周长为{}'.format(Rectangle.get_Perimeter(self)))
def __str__(self):
return str(super().get_Area())
def __repr__(self):
return str(super().get_Area())
#打印类实例
mysq=Square(40,40)
print("%s".%mysq) #打印的是str方法的返回值
print("%r".%mysq) #打印的是prep方法的返回值
mysq() #会执行__call__方法,打印正方形的周长
以下方法不常用,只做介绍
__class__ 查看类名
__base__ 查看类继承自哪个父类
__bases__ 查看继承自所有的父类
__dict__ 查看类的所有属性,以键值对方式显示