什么是Super()
如果把类比作表演者的话,Super()则是按照清单(MRO)让下一位表演者"继续"他的表演
没听明白没关系,我们通过实际的例子来逐步拆解Super()的运行逻辑,到时候我们就能明白这句话的含义
为什么要用Super()
和拆解Property一样,我们在拆解Super()前也要知道我们为什么要用它
我们同样通过实际的代码示例来理解
python
class BasicOrder:
def __init__(self, price):
self.price = price
def get_total(self):
return self.price
# 返回基础价格
class MemberOrder(BasicOrder):
def get_total(self):
return self.price * 0.9
# 返回会员折后价
class PromotionOrder(BasicOrder):
def get_total(self):
if self.price > 200:
return self.price - 20
# 满减条件
else:
return self.price
a = BasicOrder(300)
print(a.get_total())
# 原价
b = MemberOrder(300)
print(b.get_total())
# 会员折后价
c = PromotionOrder(300)
print(c.get_total())
# 满减价格
我们定义了两种折扣机制,一种是会员价,一种是满减。我们可以根据不同的折扣方式,算出打折后的价格
但是,有一种情况我们并没有考虑,那就是两种折扣同时触发的情况。如果我们规定,当两个折扣方式同时满足时,先计算会员折后价,再考虑满减,我们该如何修改这段代码呢?
很简单,我们再定义一个类,就像这样
python
class BasicOrder:
def __init__(self, price):
self.price = price
def get_total(self):
return self.price
# 返回基础价格
class MemberOrder(BasicOrder):
def get_total(self):
return self.price * 0.9
# 返回会员折后价
class PromotionOrder(BasicOrder):
def get_total(self):
if self.price > 200:
return self.price - 20
else:
return self.price
# 触发满减
class FinalOrder(MemberOrder):
def get_total(self):
member_price = MemberOrder.get_total(self)
if member_price > 200:
return member_price - 20
else:
return member_price
a = BasicOrder(300)
print(a.get_total())
# 原价
b = MemberOrder(300)
print(b.get_total())
# 会员折后价
c = PromotionOrder(300)
print(c.get_total())
# 满减价格
d = FinalOrder(300)
print(d.get_total())
# 双重折扣后的价格
如果要更换折扣顺序,先计算满减,再计算会员价,只要对FinalOrder进行修改就好
python
class FinalOrder(PromotionOrder):
def get_total(self):
count_price = PromotionOrder.get_total(self)
return count_price * 0.9
我们这种修改,在类的数量也就是折扣方式比较少时没什么问题。但如果类的数量比较多,我们就要想办法,如何不用进行这么复杂的修改。这就是我们使用super()的原因
Super()的作用
我们用super()对上面的代码进行优化
python
class BasicOrder:
def __init__(self, price):
self.price = price
def get_total(self):
return self.price
# 返回基础价格
class MemberOrder(BasicOrder):
def get_total(self):
return super().get_total() * 0.9
# 返回会员折后价
class PromotionOrder(BasicOrder):
def get_total(self):
if super().self.price > 200:
return super().get_total() - 20
else:
return super().get_total()
# 触发满减
class FinalOrder(MemberOrder, PromotionOrder):
def get_total(self):
return super().get_total()
a = BasicOrder(300)
print(a.get_total())
# 原价
b = MemberOrder(300)
print(b.get_total())
# 会员折后价
c = PromotionOrder(300)
print(c.get_total())
# 满减价格
d = FinalOrder(300)
print(d.get_total())
# 双重折扣后的价格
print(FinalOrder.mro())
# 打印Mro清单
我们要注意最后的Mro清单,它的输出结果是[<class '__main__.FinalOrder'>, <class '__main__.MemberOrder'>, <class '__main__.PromotionOrder'>, <class '__main__.BasicOrder'>, <class 'object'>]。这也就是当我们计算FinalOrder中的最后价格时,程序的执行顺序
python按照这个顺序,先从FinalOrder-MemberOrder-PromotionOrder-BasicOrder这个链条进行递进寻找,然后再从反方向BasicOrder-PromotionOrder-MemberOrder-FinalOrder进行回归计算
上面的代码就是按照这个顺序,先把原价BasicOrder给PromotionOrder计算满减,再将满减后的值给MemberOrder计算会员折扣价,最后把值给FinalOrder
return super().get_total()其实就可以理解为请MRO链条上的下一位先算出结果给我
如果我们需要改变折扣计算的方式,我们也无须对FinalOrder中的内容进行修改,只需要修改继承顺序,也就是对这个"链条"进行调整就好
当我们修改某些类名时,我们也不用像之前的"硬编码"那样逐个修改,只要确保继承的类名正确,super()会自己按照MRO这个链条进行寻找
python
class FinalOrder(PromotionOrder, MemberOrder):
def get_total(self):
return super().get_total()
结语
如果文章中有什么错误或者可以优化的地方,欢迎大家指正,感谢!