思考题:
上一章讲到了继承,一个类可以继承一个类,继承之后可以使用父类的方法和属性,那一个类可以继承多个类吗?如果可以继承多个类的话,那如果两个父类中有一样的方法的情况下,子类继承哪一个呢?
上章讲到的继承指的是子类只继承一个基类,但实际应用中有可能需要继承多个类的情况,即多继承。和实际生活联系下就明白了,一个孩子会继承父亲的一些特征,同时也会继承母亲的一些特征,可以从这个角度来理解多继承。
1、多继承
class Father: #定义父亲这个基类
def __init__(self,name,weight): #定义方法,属性
self.name = name
self.weight = weight
print("遗传父亲的体重")
class Mother: #定义母亲基类
def __init__(self,name,height):
self.name = name + "'s laopo"
self.height = height
print("遗传母亲的身高")
'''继承的顺序是先Mother后Father,即从左到右的顺序,继承了Father的weight属性和Mother的height属性'''
class Daughter(Mother,Father):
def __init__(self,name,weight,height):
Father.__init__(self,name,weight) #父类的调用
Mother.__init__(self,name,height) #父类的调用
print("女儿继承了父亲体重,母亲身高")
sp = Daughter("Jack",75,175)#Father和Mother中都有相同的方法名__init__,子类在调用时未指定,则按照从左到右的顺序查找,即调用的是Mother的方法
print(Daughter.mro()) #查看查找父类的顺序
print("名字:",sp.name) #调用
print("身高:",sp.height) #调用
print("体重:",sp.weight) #调用
'''
遗传父亲的体重
遗传母亲的身高
女儿继承了父亲体重,母亲身高
[<class '__main__.Daughter'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]
名字: Jack's laopo
身高: 175
体重: 75
'''
总结:
1、一个类可以继承多个类
2、两个父类有相同的方法名,若子类未指定继承哪一个父类,则按照从左到右的顺序查找;若指定了父类,则按照指定父类的方法
2、父类的第二种方法调用——super
super() 函数是用于调用父类的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
上面的父类调用还可以这样做:
class Father: #定义父亲这个基类
def __init__(self,name,weight): #定义方法,属性
self.name = name
self.weight = weight
print("遗传父亲的体重")
class Mother: #定义母亲基类
def __init__(self,name,height):
self.name = name + "'s laopo"
self.height = height
print("遗传母亲的身高")
'''继承的顺序是先Mother后Father,即从左到右的顺序,继承了Father的weight属性和Mother的height属性'''
class Daughter(Mother,Father):
def __init__(self,name,weight,height):
super().__init__(name,height) #父类的调用
super(Mother,self).__init__(name,weight) #父类的调用
print("女儿继承了父亲体重,母亲身高")
sp = Daughter("Jack",75,175)#Father和Mother中都有相同的方法名__init__,子类在调用时未指定,则按照从左到右的顺序查找,即调用的是Mother的方法
print(Daughter.mro()) #查看查找父类的顺序
print("名字:",sp.name) #调用
print("身高:",sp.height) #调用
print("体重:",sp.weight) #调用
'''
遗传父亲的体重
遗传母亲的身高
女儿继承了父亲体重,母亲身高
[<class '__main__.Daughter'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]
名字: Jack
身高: 175
体重: 75
'''
3、魔法方法
3.1、什么是魔法方法?
魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。它们经常是两个下划线包围来命名的(比如 __init__,__lt__),Python的魔法方法是非常强大的,所以了解其使用方法也变得尤为重要!
#拼接
a = 'hello'
b = ' world'
print(a + b)
print(a.__add__(b)) #__add__的作用等同于‘+’
'''
执行结果:
hello world
hello world
'''
class A:
def __add__(self, other): #重写__add__
print("我要飞")
a = A()
b = A()
print(a + b)
'''
执行结果:
我要飞
None
'''
class Rectangle:
def __init__(self,length,width):
self.length = length
self.width = width
def __add__(self, other):
add_length = self.length + other.length #长和长相加
add_width = self.width + other.width #宽和宽相加
return add_length,add_width
a = Rectangle(3, 4)
b = Rectangle(5, 6)
print(a + b)
3.3、类的实例调用——call方法
类的实例可以向函数一样被调用吗?
class Rectangle:
def __init__(self,length,width):
self.length = length
self.width = width
def area(self):
areas = self.length * self.width
return areas
def __call__(self):
return "this is __call__"
a = Rectangle(10,20)
print(a()) #实例对象直接调用
print("面积:",a.area())
'''
执行结果:
this is __call__
面积: 200
'''
正常情况下,实例是不能像函数一样被调用,要想实例能够被调用,则需定义__call__ 方法
3.3、魔术方法之运算方法
3.3.1、运算符方法
__add__(self,other) # x+y
__sub__(self,other) # x-y
__mul__(self,other) # x*y
__mod__(self,other) # x%y
__iadd__(self,other) # x+=y
__isub__(self,other) # x-=y
__radd__(self,other) # y+x
__rsub__(self,other) # y-x
__imul__(self,other) # x*=y
__imod__(self,other) # x%=y
3.3.2、其他魔法方法
__class__ 查看类名
__base__ 查看继承的父类
__bases__ 查看继承的全部父类
__dict__ 查看全部属性,返回属性和属性值键值对形式
__doc__ 查看对象文档,即类中的注释(用引号注视的部分)
__dir__ 查看全部属性和方法
思考题:(答案见评论区)
在“定义个矩形类,有长和宽两个实例属性, 还有一个计算面积的方法”基础上,定义正方形类。 实现类实例的可调用,调用时打印边长; 同时,直接打印类实例时能够打印出实例的面积