- 在继承问题之前先来了解下:super是什么?(后面继承代码会用到)
-
严格来说:super () 不是方法,它是一个类 !是用来创建 代理对象 的内置类!
-
super() 是 Python 内置的 类(class) ,调用 super() 其实是在 创建一个 super 对象
python# 来看下这个是什么意思? super().__init__() # 1.super() 创建一个代理对象 # 2.这个对象自动帮你找到父类 # 3.然后调用父类的 __init__ 方法
-
接下来进入正题,看下面代码为什么会报错?
python
# 爷爷类:基础用户(所有用户都有的属性)
class User:
def __init__(self, username, password):
self.username = username
self.password = password
# 父类1:会员用户
class MemberUser(User):
def __init__(self, username, password, vip_level):
# 注意这里的 super() 会自动按 MRO 顺序调用
super().__init__(username, password)
self.vip_level = vip_level
# 父类2:管理员用户
class AdminUser(User):
def __init__(self, username, password, role):
# 注意这里的 super() 会自动按 MRO 顺序调用
super().__init__(username, password)
self.role = role
# 子类:超级用户(多继承 → 既是会员,又是管理员)
class SuperUser(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() 代理对象 的顺序,这个很关键!
python# 以下两种打印方式都可以 # 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 中的代码!
python# 父类1:会员用户 class MemberUser(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() 调用的时候传了两个 ,所以缺少了一个参数,所以报错了
python# 父类2:管理员用户 class AdminUser(User): def __init__(self, username, password, role): # 注意这里的 super() 会自动按 MRO 顺序调用 super().__init__(username, password) self.role = role
-
- 问题关键:
-
第三步:解决问题
- 通过父类名方式调用父类方法,让 MemberUser 和 AdminUser 中的 super() 去找 User
-
第四步:解决后的完整代码
python# 爷爷类:基础用户(所有用户都有的属性) class User: def __init__(self, username, password): self.username = username self.password = password # 父类1:会员用户 class MemberUser(User): def __init__(self, username, password, vip_level): # 注意这里的 super() 会自动按 MRO 顺序调用 # super().__init__(username, password) # 将这里的 super() 改为 User, 注意改成这种方式后,要传递self User.__init__(self, username, password) self.vip_level = vip_level # 父类2:管理员用户 class AdminUser(User): def __init__(self, username, password, role): # 注意这里的 super() 会自动按 MRO 顺序调用 # super().__init__(username, password) # 将这里的 super() 改为 User, 注意改成这种方式后,要传递self User.__init__(self, username, password) self.role = role # 子类:超级用户(多继承 → 既是会员,又是管理员) class SuperUser(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')