一个类能够继承__init__()函数吗?(Python)

4

创建类时何时需要使用 init() 方法?

对于下面的代码,在创建 PartTimeEmployee() 类时,我们是否可以只从 Employee() 类继承 init() 方法?还是应该重新输入它?

我发现这两种代码都可以正常工作:

class Employee(object):

    def __init__(self, employee_name):
        self.employee_name = employee_name

    def calculate_wage(self, hours):
        self.hours = hours
        return hours * 20.00

class PartTimeEmployee(Employee):

    def calculate_wage(self,hours):
        self.hours = hours
        return hours * 12.00

并且

class Employee(object):

    def __init__(self, employee_name):
        self.employee_name = employee_name

    def calculate_wage(self, hours):
        self.hours = hours
        return hours * 20.00

class PartTimeEmployee(Employee):
    def __init__(self,employee_name):
        self.employee_name = employee_name

    def calculate_wage(self,hours):
        self.hours = hours
        return hours * 12.00

这里有一些最佳实践吗?

4
你可以像继承其他方法一样继承__init__。和其他方法一样,只有当你想改变它的行为时才应该重写它。 - BrenBarn
2
是的,__init__() 会被继承,就像任何其他方法一样。 - Tim Peters
1个回答

7
不需要;__init__与其他方法一样是被继承的。然而,因为这个原因,当你覆盖它时,你需要采取特殊的预防措施。例如,如果我们有一个Person类:
class Person(object):
    def __init__(self, name):
        self.name = name

我们希望创建一个名为Employee的新类,它继承自Person并添加了一个title属性。我们可以重复在Person构造函数中的逻辑:
class Employee(Person):
    def __init__(self, name, title):
        self.name = name
        self.title = title

但是如果Person做了更复杂的事情,你可能不想这样做。相反,你需要使用super显式调用超类的__init__

class Employee(Person):
    def __init__(self, name, title):
        super(Employee, self).__init__(name)
        self.title = title

但在子类没有额外初始化的简单情况下,可以自由省略__init__;它确实会从超类中适当地继承。


1
@forivall:对于大多数方法来说,这是一个有效的观点,但我会特别排除 __init__;如果您已经有了类型的引用以创建它的实例,那么您几乎可以确定您将要创建哪种类型的实例,因此可以传递您知道它需要的任何参数。 - icktoofay
4
改变 __init__ 函数签名的好处很多,实际上,Python 的标准库经常这样做。当你需要一个“工厂函数”来为层次结构中的所有类提供相同的接口时,你要么需要它们具有相同的 __init__ 函数签名,要么使用一些 @classmethod 替代……但这不是常见的情况(除非你试图在 Python 中编写 Java 代码)。 - abarnert
1
例如,在Python文档中搜索“subclass”的第一个结果是HTTPSConnection。将其与其基类进行比较。 - abarnert
1
@Akavall:没错,但是super以一种非常特殊的方式处理多重继承,这可能是需要的。 - icktoofay
1
@Akavall:实际上,你唯一需要编写 Person.__init__ 的情况是 (a) 基类是旧式类,或者 (b) 你特别想避免正常的方法解析顺序。如果在不必要的情况下这样做,读者会怀疑其中一个情况是真的,并浪费时间试图弄清楚你的意图。此外,这会使你的代码更加脆弱——如果你稍后插入一个中间类,你必须记得修改所有派生类的 __init__ 方法,漏掉一个将导致一个噩梦般难以找到的错误。 - abarnert
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接