Calling super().__init__(**kwargs), and multiple inheritance?
我正在努力学习和理解如何在Python中使用super,我一直在遵循"从新手到专家的Python旅程",尽管我觉得我理解这个概念,但在自己的代码中执行super时遇到了问题。
例如,此方法适用于我:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class Employee: def __init__(self, firstname, lastname, age, sex, dob): self.firstname = firstname self.lastname = lastname self.age = age self.sex = sex self.dob = dob self.all_staff.append(self) class Hourly(Employee): def __init__(self, firstname, lastname, age, sex, dob, rate, hours): self.rate = rate self.hours = hours super().__init__(firstname, lastname, age, sex, dob) def __str__(self): return"{} {} Age: {} Sex: {} DOB: {} ".format(self.firstname, self.lastname, self.age, self.sex, self.dob) def get_rate(self): print('The hourly rate of {} is {} '.format(self.firstname, self.rate)) hourlystaff1 = Hourly('Bob', 'Foo', '23', 'M', '12/1/1980', '$15', '30') print(hourlystaff1) print(hourlystaff1.get_rate()) |
返回以下内容:
1 2 3 4 5 6 7 | Bob Foo Age: 23 Sex: M DOB: 12/1/1980 The hourly rate of Bob is $15 None |
这正是我所期望的(我不确定为什么"无"也会被退回,也许有人能解释?).
然后我想用super来试试这个,但是要用**kwargs,就像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Employee: def __init__(self, firstname='', lastname='', age='', dob='', **kwargs): super().__init__(**kwargs) self.firstname = firstname self.lastname = lastname self.age = age self.dob = dob class Hourly(Employee): def __init__(self, rate=''): self.rate = rate super().__init__(**kwargs) def __str__(self): return"{} {} Age: {} Sex: {}".format(self.firstname, self.lastname, self.age, self.sex, self.dob, self.rate) def get_rate(self): print('The hourly rate of {} is {} '.format(self.firstname, self.rate)) bob = Hourly('Bob', 'Bar', '23', '12/1/2019') bob.get_rate('$12') |
返回此错误:
1 2 3 | File"staff_b.py", line 33, in <module> bob = Hourly('Bob', 'Bar', '23', '12/1/2019') TypeError: __init__() takes from 1 to 2 positional arguments but 5 were given |
在第二种方法中我做错了什么?如何正确使用**Kwargs和Super?
编辑:
这是本书中一个示例的屏幕截图,我一直在关注:
在第二个例子中,我如何使用**Kwargs和super有什么不同?
这也是同一本书和同一章的综合案例研究。这对我有用,我理解它是如何工作的,但我似乎无法将它翻译成我自己的作品。
https://pastebin.com/nygjfmik网站
你在这里看到的水泡并不是针对超级水泡,而是针对夸格斯水泡。如果我们丢弃了您的大部分代码并删除super,它看起来是这样的:
1 2 3 4 5 6 7 | class Hourly(Employee): def __init__(self, rate=''): self.rate = rate some_crazy_function(**kwargs) hourlystaff1 = Hourly('Bob', 'Foo', '23', 'M', '12/1/1980', '$15', '30') |
有两个明显的问题:
1 2 3 4 5 6 7 8 9 | class Process: def __init__(self, exe): self.exe = exe self.run() class DownloadExecutableBeforeProcess(Process): def __init__(self, exe): self.download_exe(exe) Process.__init__(self, exe) |
这里我们正在进行继承,甚至不需要使用super——我们可以显式地使用superclass的名称,并拥有我们想要的行为。我们可以在这里重写使用
1 2 3 4 5 6 7 8 9 | class AuthenticationCheckerProcess(Process): def __init__(self, exe, use_sha=True): self.check_if_authorized(exe, use_sha) Process.__init__(self, exe) class DownloadAndCheck(DownloadExecutableBefore, AuthenticationCheckerProcess): def __init__(self, exe): DownloadExecutableBefore.__init__(exe) AuthenticationCheckerProcess.__init__(exe, use_sha=False) |
如果按照EDOCX1的初始值(9),我们会看到
1 2 3 4 | class DownloadAndCheck(DownloadExecutableBefore, AuthenticationCheckerProcess): def __init__(self, exe): super().__init__(exe, use_sha=False) # also replace the Process.__init__ cals in the other classes with super |
1 2 3 4 5 6 7 8 9 10 11 12 | class Process: def __init__(self, exe, **kwargs): # accept arbitrary keywoards but ignore everything but exe # also put **kwargs in all other initializers self.exe = exe self.run() class DownloadExecutableBeforeProcess(Process): def __init__(self, exe, **kwargs): self.download_exe(exe) # pass the keywoards into super so that other __init__s can use them Process.__init__(self, exe, **kwargs) |
现在,
因此,如果您有多个继承并使用不同的(keywoard)参数super和kwargs可以解决您的问题。但是超级继承和多重继承是复杂的,特别是如果您有比这里更多的继承层。有时甚至没有定义函数的调用顺序(然后python应该抛出一个错误,参见例如mro算法更改的解释)。mixin甚至可能需要一个
这应该管用
1 2 3 4 5 6 | class Employee: def __init__(self, firstname='', lastname='', age='', dob=''): self.firstname = firstname self.lastname = lastname self.age = age self.dob = dob |
那你要上儿童班了
1 2 3 4 5 6 7 | class Hourly2(Employee): def __init__(self,*args, **kwargs): super(Hourly2,self).__init__(*args, **kwargs) def get_rate(self,rate=None): self.data=rate print ('My hourly rate is {}'.format(self.data)) |
现在,让我们举个例子
1 | bob = Hourly2('Bob', 'Bar', '23', '12/1/2019') |
我们可以检查属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | dir(bob) ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'dob', 'firstname', 'get_rate', 'lastname'] |
终于
1 2 | bob.age '23' |
和
1 2 | bob.get_rate('$12') My hourly rate is $12 |