我试图理解为什么我的代码表现得如此。基本上,我以两种方式创建了父类和子类。我想发生的是,在为两个类创建的每个实例上, init 方法将更新每个类的num_of_emps计数。所以,如果我有类似的东西:
class Employee:
num_of_emps = 0
def __init__(self, first, last, pay, division):
self.first = first
self.last = last
self.pay = pay
self.division = division
Employee.num_of_emps += 1
class Manager(Employee):
num_of_emps = 0
def __init__(self, first, last, pay, division):
self.first = first
self.last = last
self.pay = pay
self.division = division
Manager.num_of_emps += 1
emp1 = Employee("Dallas", "Mat", 100000, "Sales")
emp2 = Employee("Mark", "Doe", 50000, "Marketing")
emp3 = Employee("Jane", "Doe", 50000, "Advertisement")
man1 = Manager("Bob", "Ben", 200000, "Marketing")
man2 = Manager("Ryan", "DS", 200000, "Advertisement")
# Employee.num_of_emps returns 3
# Manager.num_of_emps returns 2
这就是我想要的。但是,如果我添加super。 init ()方法,而不是对Manager类的属性进行硬编码,则会发生其他事情:
class Employee:
num_of_emps = 0
def __init__(self, first, last, pay, division):
self.first = first
self.last = last
self.pay = pay
self.division = division
Employee.num_of_emps += 1
class Manager(Employee):
num_of_emps = 0
def __init__(self, first, last, pay, division):
super().__init__(first, last, pay, division)
Manager.num_of_emps += 1
emp1 = Employee("Dallas", "Mat", 100000, "Sales")
emp2 = Employee("Mark", "Doe", 50000, "Marketing")
emp3 = Employee("Jane", "Doe", 50000, "Advertisement")
man1 = Manager("Bob", "Ben", 200000, "Marketing")
man2 = Manager("Ryan", "DS", 200000, "Advertisement")
# Employee.num_of_emps returns 5
# Manager.num_of_emps returns 2
让我感到困惑的是,每次创建管理器实例时,父类的num_of_emps也会更新。我知道super()。 init 方法是造成这种情况的原因,但是有人可以解释原因吗?
答案 0 :(得分:1)
这是因为super()。 init ()调用了super init方法。然后用这种方法增加Manager的数量。这是继承的问题。更好的方法可能是更好地细分您的课程。
在another answer中还给出了另外两个建议,这些建议的结构比我提供的代码示例更好,它们旨在尝试展示如何尽可能简单地划分您的问题。
class Person:
def __init__(self):
# Some stuff
pass
class Employee(Person):
counter = 0
def __init__(self):
super().__init__()
# Some stuff
Employee.counter += 1
pass
class Manager(Person):
counter = 0
def __init__(self):
super().__init__()
# Some stuff
Manager.counter += 1
pass
这将避免在基类上多次触发counter属性。
答案 1 :(得分:1)
您已经对“为什么”部分有了答案,所以我不再重复。
对于您而言,对于该解决方案,只需避免对类名进行硬编码(使用type(self)
来获取当前实例的类)就可以解决此问题(nb:如果您考虑更新Employee
计数器是一个问题):
>>> class Base(object):
... counter = 0
... def __init__(self):
... print("base.__init__")
... type(self).counter += 1
...
>>> class Child(Base):
... pass
...
>>> c = Child()
base.__init__
>>> Base.counter
0
>>> Child.counter
1
一种更清洁的解决方案是在类方法中排除计数器增量,以便您既可以拥有预期的默认值,又可以在需要时覆盖它,即:
>>> class Base(object):
... counter = 0
... def __init__(self):
... self.inc_counter()
... @classmethod
... def inc_counter(cls):
... cls.counter += 1
...
>>> class Child(Base):
... pass
...
>>> c = Child()
>>> Child.counter
1
>>> Base.counter
0