调用super().__ init __(** kwargs)和多重继承?

妖精火箭

我正在尝试学习和理解如何在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())

返回以下内容:

Bob Foo
Age: 23
Sex: M
DOB: 12/1/1980

The hourly rate of Bob is $15 
None

这就是我的预期(我不确定为什么也返回“ 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有什么区别?

这也是同一本书和同一章中的综合案例研究。这对我有用,我知道它是如何工作的,但是我似乎无法将其转换为我自己的作品。

https://pastebin.com/NYGJfMik

同义词

您在这里所遇到的问题并不是真正针对super的,而是针对kwargs的。如果我们丢掉大部分代码并删除超级代码,则它看起来像这样:

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')

有两个明显的问题:__init__函数传递的参数比预期的要多,并且__init__函数主体中的引用在kwargs任何地方都未定义。在这里,理解**kwargs(及其兄弟姐妹*args)足以在此处解决问题,**kwargs并且非常有用。首先让我们看一下为什么super有用。假设我们使用一些不错的辅助方法在子流程周围编写了一些包装器(该体系结构可能不是最适合该问题的方法,但是仅看到具有继承性的动物也无济于事。多重继承是一种罕见的情况,因此很难提出不是动物,游戏实体或GUIwidgets的好例子):

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-我们可以仅显式使用超类的名称,并具有我们想要的行为。我们可以重写以super在此处使用,但不会改变行为。如果您仅从一个类继承,则您并不需要super,尽管它可以帮助您不重复继承的类名。让我们增加类的层次结构,并包括多个类的继承:

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)

如果我们遵循init的初始化DownloadAndCheckProcess.__init__则会看到它被调用了两次,一次通过DownloadExecutableBefore.__init__,一次通过AuthenticationCheckerProcess.__init__因此,我们要包装的过程也运行了两次,这不是我们想要的。在此示例中,我们可以通过不调用self.run()流程的init来轻松解决此问题,但是在现实世界中,这并非总是那么容易解决。Process.__init__在这种情况下,调用似乎是错误的。我们可以以某种方式解决此问题吗?

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

super解决此问题,并且只会调用Process.__init__一次。它还将照顾该函数应运行的顺序,但这不是一个大问题。我们仍然有一个问题:use_sha=False将传递给所有初始化程序,但实际上只有一个需要它。我们不能只将变量仅传递给需要它的函数(因为弄清楚这将是一场噩梦),但是我们可以教其他__init__变量忽略键值:

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)

现在,super().__init__(exe, use_sha=False)调用将成功,每个初始化器仅采用其理解的键值,并将其他键值进一步传递下去。

因此,如果您具有多重继承并且使用不同的(keywoard)参数,super和kwargs可以解决您的问题。但是超级继承和多重继承很复杂,尤其是如果您的继承层比这里多。有时甚至没有定义应调用函数的顺序(然后python应该抛出错误,例如参见MRO算法更改说明)。super().__init__()尽管Mixins甚至不从任何类继承,但它们甚至可能需要调用。总而言之,如果您使用多重继承,则会在代码中带来很多复杂性,因此,如果您真的不需要它,通常最好考虑使用其他方法来建模问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

多重继承Python,super().__ init__问题

来自分类Dev

多重继承并调用super()

来自分类Dev

为什么在具有多重继承的 super() 时不能调用所有 __init__ ?

来自分类Python

多重继承如何与super()和不同的__init __()参数一起使用?

来自分类Dev

Python多重继承和super()

来自分类Dev

Python中的多重继承-调用__init__时出错

来自分类Dev

多重继承:包含super()调用的重写方法

来自分类Python

Python的多重继承:选择要调用的super()

来自分类Dev

Python多重继承:全部调用super

来自分类Linux

当直接从`object`继承时,我应该调用super().__ init __()吗?

来自分类Dev

继承和构造函数。自己在 super.init 之前使用

来自分类Dev

什么时候调用Python的super().__ init __()?

来自分类Dev

使用必需的init从super继承Swift 5

来自分类Python

用多重继承调用父类__init__,正确的方法是什么?

来自分类Python

用多重继承调用父类__init__,正确的方法是什么?

来自分类Dev

如果仅调用super .__ init__是必需的__init__吗?

来自分类Dev

使用super()混合type()和自定义__init __().__ init __()

来自分类Python

为什么在多次继承中执行Base .__ init __(self)而不是super().__ init __()时会跳过__init__?

来自分类Dev

__init__不被双继承类调用

来自分类Dev

Swift super.init() - 属性未在 super.init 调用中初始化

来自分类Dev

继承和__init__

来自分类Dev

只要init调用[super init],在Objective C自定义init方法中调用[self init]是否可以?

来自分类Dev

Python:在多重继承中呼叫多个init

来自分类Dev

super.init调用未初始化属性“ self。*”

来自分类Dev

__init__可以在调用super之后自动执行代码吗?

来自分类Dev

调用super的init时,Python中的最大递归深度错误。

来自分类Dev

属性未在super.init调用中初始化

来自分类Dev

快速子类是否总是必须调用super.init()

来自分类Dev

在super.init调用之前使用“自我”

Related 相关文章

  1. 1

    多重继承Python,super().__ init__问题

  2. 2

    多重继承并调用super()

  3. 3

    为什么在具有多重继承的 super() 时不能调用所有 __init__ ?

  4. 4

    多重继承如何与super()和不同的__init __()参数一起使用?

  5. 5

    Python多重继承和super()

  6. 6

    Python中的多重继承-调用__init__时出错

  7. 7

    多重继承:包含super()调用的重写方法

  8. 8

    Python的多重继承:选择要调用的super()

  9. 9

    Python多重继承:全部调用super

  10. 10

    当直接从`object`继承时,我应该调用super().__ init __()吗?

  11. 11

    继承和构造函数。自己在 super.init 之前使用

  12. 12

    什么时候调用Python的super().__ init __()?

  13. 13

    使用必需的init从super继承Swift 5

  14. 14

    用多重继承调用父类__init__,正确的方法是什么?

  15. 15

    用多重继承调用父类__init__,正确的方法是什么?

  16. 16

    如果仅调用super .__ init__是必需的__init__吗?

  17. 17

    使用super()混合type()和自定义__init __().__ init __()

  18. 18

    为什么在多次继承中执行Base .__ init __(self)而不是super().__ init __()时会跳过__init__?

  19. 19

    __init__不被双继承类调用

  20. 20

    Swift super.init() - 属性未在 super.init 调用中初始化

  21. 21

    继承和__init__

  22. 22

    只要init调用[super init],在Objective C自定义init方法中调用[self init]是否可以?

  23. 23

    Python:在多重继承中呼叫多个init

  24. 24

    super.init调用未初始化属性“ self。*”

  25. 25

    __init__可以在调用super之后自动执行代码吗?

  26. 26

    调用super的init时,Python中的最大递归深度错误。

  27. 27

    属性未在super.init调用中初始化

  28. 28

    快速子类是否总是必须调用super.init()

  29. 29

    在super.init调用之前使用“自我”

热门标签

归档