- 在继承问题之前先来了解下:super是什么?(后面继承代码会用到)
- 严格来说:super () 不是方法,它是一个类!是用来创建代理对象的内置类!
- super() 是 Python 内置的类(class),调用 super() 其实是在 创建一个super 对象
# 来看下这个是什么意思?super().__init__()# 1.super() 创建一个代理对象# 2.这个对象自动帮你找到父类# 3.然后调用父类的 __init__ 方法
接下来进入正题,看下面代码为什么会报错?
# 爷爷类:基础用户(所有用户都有的属性)classUser:def__init__(self,username,password):self.username=username self.password=password# 父类1:会员用户classMemberUser(User):def__init__(self,username,password,vip_level):# 注意这里的 super() 会自动按 MRO 顺序调用super().__init__(username,password)self.vip_level=vip_level# 父类2:管理员用户classAdminUser(User):def__init__(self,username,password,role):# 注意这里的 super() 会自动按 MRO 顺序调用super().__init__(username,password)self.role=role# 子类:超级用户(多继承 → 既是会员,又是管理员)classSuperUser(MemberUser,AdminUser):def__init__(self,username,password,vip_level,role):# 手动初始化两个父类MemberUser.__init__(self,username,password,vip_level)AdminUser.__init__(self,username,password,role)super_user=SuperUser('test','123456','3','test_user')报错信息:TypeError: AdminUser.init() missing 1 required positional argument: ‘role’。AdminUser类 为什么会缺少一个位置参数呢?
- 第一步:我们从头开始捋
- 代码从实例化 SuperUser 子类开始
- SuperUser 又是多继承
- 那么我们来看 SuperUser 子类的mro顺序,也就是继承的顺序,也就是super() 代理对象的顺序,这个很关键!
# 以下两种打印方式都可以# print(SuperUser.__mro__) # 这种打印出来是元组print(SuperUser.mro())# 这种打印出来是列表,这里用这个了# 打印结果:# [<class '__main__.SuperUser'>, <class '__main__.MemberUser'>, <class '__main__.AdminUser'>, <class '__main__.User'>, <class 'object'>]# 这里继承的顺序很关键:SuperUser -- MemberUser -- AdminUser -- User -- object - 第二步:我们知道了继承的顺序,先是 SuperUser 本身,这里没什么问题,然后是MemberUser ,再然后是AdminUser… 此时我们来看下MemberUser中的代码!
# 父类1:会员用户classMemberUser(User):def__init__(self,username,password,vip_level):# 注意这里的 super() 会自动按 MRO 顺序调用super().__init__(username,password)self.vip_level=vip_level# mro继承顺序很关键:SuperUser -- MemberUser -- AdminUser -- User -- object- 问题关键:
- 来看下上面代码的super()
- 我们的本意是要让他调用 User 爷爷类的初始化方法
- 但是现在按照mro顺序实际找的是 MemberUser 下一个类,也就是AdminUser类
- 相当于这里的 super() 调用的是 AdminUser 类中的 初始化方法
- AdminUser 中的__init__需要三个参数,但是 MemberUser 中 super() 调用的时候传了两个,所以缺少了一个参数,所以报错了
# 父类2:管理员用户classAdminUser(User):def__init__(self,username,password,role):# 注意这里的 super() 会自动按 MRO 顺序调用super().__init__(username,password)self.role=role
- 问题关键:
- 第三步:解决问题
- 通过父类名方式调用父类方法,让 MemberUser 和 AdminUser 中的 super() 去找 User
- 第四步:解决后的完整代码
# 爷爷类:基础用户(所有用户都有的属性)classUser:def__init__(self,username,password):self.username=username self.password=password# 父类1:会员用户classMemberUser(User):def__init__(self,username,password,vip_level):# 注意这里的 super() 会自动按 MRO 顺序调用# super().__init__(username, password)# 将这里的 super() 改为 User, 注意改成这种方式后,要传递selfUser.__init__(self,username,password)self.vip_level=vip_level# 父类2:管理员用户classAdminUser(User):def__init__(self,username,password,role):# 注意这里的 super() 会自动按 MRO 顺序调用# super().__init__(username, password)# 将这里的 super() 改为 User, 注意改成这种方式后,要传递selfUser.__init__(self,username,password)self.role=role# 子类:超级用户(多继承 → 既是会员,又是管理员)classSuperUser(MemberUser,AdminUser):def__init__(self,username,password,vip_level,role):# 手动初始化两个父类MemberUser.__init__(self,username,password,vip_level)AdminUser.__init__(self,username,password,role)super_user=SuperUser('test','123456','3','test_user')