我正在努力学习和理解如何在Python中使用super,我一直在关注《Python从新手到专家的旅程》一书,尽管我觉得我理解了在我自己的代码中执行super时遇到问题的概念。在
例如,这种方法适用于我:
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 "{} {}\nAge: {}\nSex: {}\nDOB: {}\n".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())
返回以下值:
^{pr2}$这就是我所期望的(我不确定为什么“None”也被返回,也许有人可以解释一下?)。在
然后我想用super来试试这个,但是使用的是**kwargs:
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 "{} {}\nAge: {}\nSex: {}".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')
返回此错误:
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有什么不同?在
这也是同一本书和同一章的综合案例研究。这对我很有用,我理解它的工作原理,但我似乎无法将其转化为我自己的工作。在
你在这里遇到的问题并不是针对超级,而是针对夸克。如果我们扔掉你的大部分代码并删除了super,它看起来像这样:
有两个明显的问题:}是非常有用的。让我们先看看
^{pr2}$__init__
函数传递的参数比预期的多,并且在__init__
函数的主体中引用了没有在任何地方定义的kwargs
。而在这里,理解**kwargs
(及其兄弟*args
)就足以解决这里的问题super和{super
为什么有用。让我们想象一下,我们用一些很好的辅助方法为子流程编写一些包装器(体系结构可能不是解决问题的最佳方法,但是只有看到具有继承性的动物也没有什么特别的帮助。多重继承是一种非常罕见的情况,因此很难找到不是动物、游戏实体或GUIwidgets的好例子):在这里,我们正在进行继承,甚至不需要使用super-我们可以显式地使用超类的名称并获得我们想要的行为。我们可以在这里重写以使用
super
,但它不会改变行为。如果只从一个类继承,则不需要super
,尽管它可以帮助您避免重复从中继承的类名。让我们加入我们的类层次结构,包括来自多个类的输入:如果我们遵循},一次是通过{}!所以我们要包装的过程也运行了两次,这不是我们想要的。在这个例子中,我们可以通过不在进程初始化中调用
DownloadAndCheck
的初始化,我们会看到Process.__init__
被调用了两次,一次是通过{self.run()
来轻松地解决这个问题,但在现实世界中,这并不总是像这里这样容易修复。在这种情况下,调用Process.__init__
似乎是错误的。我们能解决这个问题吗?在super
修复了这个问题,并且只调用Process.__init__
一次。它还将处理函数的运行顺序,但这不是一个大问题。我们仍然有一个问题:use_sha=False
将被传递给所有初始化器,但只有一个真正需要它。我们真的不能只将变量传递给需要它的函数(因为弄清楚这将是一场噩梦),但我们可以教导其他__init__
忽略keywoard:现在
super().__init__(exe, use_sha=False)
调用将成功,每个初始值设定项只接受它能理解的keywoard,并简单地将其他密钥向下传递。在因此,如果您有多个继承并使用不同的(keywoard)参数super和kwargs可以解决您的问题。但是超级继承和多重继承是复杂的,特别是如果你有比这里更多的继承层。有时甚至没有定义调用函数的顺序(python应该抛出一个错误,参见explenation of change of MRO algorithm)。mixin甚至可能需要一个
super().__init__()
调用,尽管它们甚至不从任何类继承。总之,如果您使用多重继承,您的代码会变得非常复杂,因此,如果您不需要它,通常最好考虑其他方法来建模您的问题。在这应该行得通
那你就上儿童班了
^{pr2}$现在,让我们举个例子
我们可以检查属性
最后
以及
相关问题 更多 >
编程相关推荐