Python类的约束以及super()剖析
1.类的约束
第一版:
class WechatPay:
def pay(self):
print("微信支付")
class AliPay:
def pay(self):
print("支付宝支付")
class QQpay:
def fuqian(self):
print("QQ支付")
wei = WechatPay()
ali = AliPay()
qq = QQpay()
wei.pay()
ali.pay()
qq.fuqian()
# 当统一接口时
def pay(object):
object().pay() # QQ支付无法实现归一化
第二版:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴,
互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
class PayClass:
def pay(self):
pass
class WechatPay(PayClass):
def pay(self):
print("微信支付")
class AliPay(PayClass):
def pay(self):
print("支付宝支付")
class QQpay(PayClass):
def fuqian(self):
print("QQ支付")
def pay(object):
object().pay()
pay(WechatPay)
pay(QQpay) # QQpay会执行父类的pay方法但是无法完成支付
(1)对类的约束有两种:
<1> 提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了. 这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错.
<2> 使⽤元类来描述⽗类. 在元类中给出⼀个抽象⽅法. 这样⼦类就不得不给出抽象⽅法的具体实现. 也可以起到约束的效果.
第三版:
# 方式一: (推荐并且常用的方式)
# raise 主动抛出异常(主动报错)
class PayClass:
def pay(self):
raise Exception("你子类必须要写一个pay方法")
class WechatPay(PayClass):
def pay(self):
print("微信支付")
class AliPay(PayClass):
def pay(self):
print("支付宝支付")
class QQpay(PayClass):
def fuqian(self):
print("QQ支付")
def pay(object):
object().pay()
pay(WechatPay)
pay(QQpay) # QQpay类中没有pay方法,raise就会主动抛出异常(主动报错)
# 方法二
# 抽象类,接口类: 制定一些规则
from abc import ABCMeta,abstractmethod # 抽象类,接口类
class PayClass(metaclass=ABCMeta): # 元类
@abstractmethod
def pay(self):
raise Exception("你子类必须要写一个pay方法")
class WechatPay(PayClass):
def pay(self):
print("微信支付")
class AliPay(PayClass):
def pay(self):
print("支付宝支付")
class QQpay(PayClass):
def fuqian(self):
print("QQ支付")
def pay(object):
object().pay()
pay(WechatPay)
pay(AliPay)
pay(QQpay) # QQpay类中没有pay方法,就会与指定的规则不符导致报错
总结:
约束. 其实就是⽗类对⼦类进⾏约束. ⼦类必须要写xxx⽅法. 在python中约束的⽅式和⽅法有两种:
-
使⽤抽象类和抽象⽅法, 由于该⽅案来源是java和c#. 所以使⽤频率还是很少的
-
使⽤⼈为抛出异常的⽅案. 并且尽量抛出的是NotImplementError. 这样比较专业, ⽽且错误比较明确.(推荐)
2.super 剖析
super是严格按照类的继承顺序执行
class A:
def f1(self):
print('in A')
class Foo(A):
def f1(self):
super().f1()
print('in Foo')
class Bar(A):
def f1(self):
print('in Bar')
class Info(Foo,Bar):
def f1(self):
# super里的类名是指定查找mro中类名的下一个类, self是指定查找时使用的mro顺序
super(Info,self).f1() # Foo() 对象的内存地址 # super(子类名,子类的mro列表)
print('in Info f1')
aa = Info() # 对象的内存地址
aa.f1()
# Info [Info', Foo', Bar', A', 'object']
a = Foo()
b = a
print(a)
print(b)
print(Info.mro())
obj = Info()
obj.f1()