从另一个子类继承的“无法创建一致的方法解析顺序”

时间:2019-03-10 19:22:16

标签: python python-3.x oop inheritance

我正在用Python修改OOP,并尝试从另一个子类继承属性,但是我不知道该怎么做或是否可行。这是我到目前为止的内容:

SQL> with test (col) as
  2    (select 'a. Little foot, c-f Bruce Wayne, Catherine Zeta-Jones, b. Bill White Jr.' from dual),
  3  inter as
  4    (select trim(regexp_substr(col, '[^,]+', 1, level)) str
  5     from test
  6     connect by level <= regexp_count(col, ',') + 1
  7    ),
  8  inter2 as
  9    (select trim(replace(replace(replace(str, 'a.', ''),
 10                                              'b.', ''),
 11                                              'c-f', '')) result,
 12       rownum rn
 13     from inter
 14    )
 15  select max(decode(rn, 1, result)) n1,
 16         max(decode(rn, 2, result)) n2,
 17         max(decode(rn, 3, result)) n3,
 18         max(decode(rn, 4, result)) n4
 19  from inter2;

N1                   N2                   N3                   N4
-------------------- -------------------- -------------------- --------------------
Little foot          Bruce Wayne          Catherine Zeta-Jones Bill White Jr.

SQL>

我收到的错误是:

class Employee:
  def __init__(self, first, last, pay):
    self.first = first
    self.last = last
    self.pay = pay
  def increase_pay(self, multiplier):
   self.pay = int(self.pay * multiplier)

class Developer(Employee):
  def __init__(self, first, last, pay, prog_lang):
    Employee.__init__(self, first, last, pay)
    self.prog_lang = prog_lang
    self.email = first.lower() + '.' + last.lower() + '@outlook.com'

class beta_Tester(Employee, Developer):
  def __init__(self, first, last, pay, prog_lang, platform):
    self.platform = platform    

3 个答案:

答案 0 :(得分:2)

方法解析顺序(MRO)由C3线性化算法定义,这听起来很复杂,但实际上可以归结为:类,其父级,父级等都需要放置符合两个条件的列表中:

  1. 每个类出现在其父类之前
  2. 如果某个类别从一个以上的类别继承,则其父级会出现在同一个类别中  顺序与class语句中的顺序相同。也就是说,给定class A(B, C, D)A的MRO将在B之前有C,而D之前。 (当然,A出现在所有3之前)

您应该能够看到问题:通过这种算法,beta_Tester的MRO必须根据第一条规则在Developer之前包含Employer,但是Employer必须根据第二条规则在Developer之前。在这种情况下,您可以简单地将两者互换以解决问题,但没有任何理由要从类A 继承自A的另一个类。完全放开A

# Developer is already a descendent of Employee, so BetaTester will be, too
class BetaTester(Developer):
   ...

要确保调用每个类的__init__方法,请使用super确保每个__init__调用链中的下一个方法。这里最重要的规则是确保如果类将参数添加到__init__,则必须确保 not 将其传递给下一个__init__。同时,它必须接受任意关键字参数,并且要确保将其传递给。关键字参数使您可以更轻松地集中精力处理需要处理的参数,而只需传递不需要的参数即可。

class Employee:
    def __init__(self, first, last, pay, **kwargs):
        super().__init__(**kwargs)
        self.first = first
        self.last = last
        self.pay = pay
    def increase_pay(self, multiplier):
        self.pay = int(self.pay * multiplier)


class Developer(Employee):
    def __init__(self, prog_lang, **kwargs):
        super().__init__(**kwargs)
        self.prog_lang = prog_lang
        self.email = "{}.{}@outlook.com".format(self.first.lower(), self.last.lower())


class BetaTester(Developer):
    def __init__(self, platform, **kwargs):
        super().__init__(**kwargs)
        self.platform = platform    


b = BetaTester(first="Bob", last="Jones", pay=90000, prog_lang="Python", platform="Unix")

答案 1 :(得分:1)

  1. 在子类的super()方法中使用__init__
  2. 您的beta_Tester继承自EmployeeDeveloper。由于Developer已经继承自Employee,Python现在无法确定首先查找哪种方法的类。您无需在此处命名Developer的所有基类;只是从那一类继承而来。

这是您的固定代码:

class Employee:
  def __init__(self, first, last, pay):
    self.first = first
    self.last = last
    self.pay = pay


  def increase_pay(self, multiplier):
   self.pay = int(self.pay * multiplier)

emp_1 = Employee('David', 'Jackson', 35000)

print (emp_1.pay)

emp_1.increase_pay(1.2)

print (emp_1.pay)

class Developer(Employee):
  def __init__(self, first, last, pay, prog_lang):
    super().__init__(first, last, pay)
    self.prog_lang = prog_lang
    self.email = first.lower() + '.' + last.lower() + '@outlook.com'



dev_1 = Developer('James', 'McCarthy', 70000, 'C++',)

print(dev_1.first)
print(dev_1.email)


class beta_Tester(Developer):
  def __init__(self,first, last, pay, prog_lang, platform):
    self.platform = platform

bt_1 = beta_Tester('Jonas', 'Andersen', 45000, 'C#', 'Mobile')

print(bt_1.platform)

答案 2 :(得分:1)

@MehrdadEP回答得很好

我想我应该变得容易

假设有A和B两类

B继承自A

现在您要创建一个新的C类

如果您从B继承,那么您已经在从A继承。无需在C(A,B)类中编写它

观察C(B,A)不会给您错误 但是C(A,B)会

另一件事是,您应该使用Super().__init__()而不是Employee.__init__() 在进行混合继承时,这可能并不方便,因为您必须调用classname1.__init__() , classname2.__init__()等多个不同的超类,

还要确保是否要在SuperClass中定义属性,然后调用classname.__init__(),以便在新类的作用域中定义它们;否则 您将收到错误

例如

print(b1_1.first)将给出错误 解决使用Developer.__init__(self, first, last, pay, prog_lang)

也不要忘记从子类Developer.__init__进行的__init__调用中的自我