子类构造函数引发TypeError:__init __()接受2个位置参数,但给出了5个位置

时间:2018-10-29 10:23:32

标签: python python-3.x class inheritance

这是我使用Python中的类和继承的第一天,所以请对我保持谨慎。我有两个类,分别是Person和Employee,其中Employee是Person的子类。

class Person:
    def __init__(self, name, place, age, sex):
        self.name = name
        self.place = place
        self.age = age
        self.sex = sex

class Employee(Person):
    def __init__(self, emp_id):
        self.emp_id = emp_id

现在,我正在尝试如下创建Employee类的实例:

In [9]: A = Employee('Jack', 'Rome', 23, 'M')
TypeError: __init__() takes 2 positional arguments but 5 were given

我在做什么错了?

6 个答案:

答案 0 :(得分:2)

Python在创建类时几乎没有“魔力”-您通常可以准确地获得所指定的内容。在您的情况下,您指定了初始化Employee仅采用一个附加参数:

class Employee(Person):
    # Employee initialises itself with one argument
    def __init__(self, emp_id):
        self.emp_id = emp_id

这意味着说Employee(1287123)是有效的,但不是Employee('Jack', 'Rome', 23, 'M')。对于类EmployeeEmployee.__init__隐藏了Person.__init__

>>> Employee.__init__
<function __main__.Employee.__init__(self, emp_id)>
>>> Person.__init__
<function __main__.Person.__init__(self, name, place, age, sex)>
>>> Employee.__init__ is Person.__init__
False

如果您希望EmployeePerson一样初始化,则必须这样明确地说:

class Employee(Person):
    # Employee initialises itself like Person plus one argument
    def __init__(self, name, place, age, sex, emp_id):
        # initialise self like a Person
        Person.__init__(self, name, place, age, sex)
        # initialise self like an Employee *in addition*
        self.emp_id = emp_id

优良作法是不要直接调用基类的方法。相反,内置的super允许从继承层次结构中动态调用方法:

class Employee(Person):
    # Employee initialises itself like Person plus one argument
    def __init__(self, name, place, age, sex, emp_id):
        # initialise self like a Person
        super().__init__(name, place, age, sex)
        # initialise self like an Employee *in addition*
        self.emp_id = emp_id

super的目的是削弱继承的耦合。例如,您可以将基类Person交换为其他内容,而__init__方法仍然可以使用。另请参见How does Python pass __init__ parameters with multiple inheritance

代替手动传递参数,可以使用***捕获任何未使用的位置和命名参数:

class Employee(Person):
    # Employee initialises itself with one argument
    # other positional and keyword arguments are passed to the superclass
    def __init__(self, *args, emp_id, **kwargs):
        # initialise self like the superclass
        super().__init__(*args, **kwargs)
        # initialise self like an Employee *in addition*
        self.emp_id = emp_id

答案 1 :(得分:1)

如果您要覆盖__init__或其他任何方法,也需要接受父类参数

class Employee(Person):
    def __init__(self, name, place, age, sex, emp_id):
        super(Employee, self).__init__(name, place, age, sex)
        self.emp_id = emp_id

>>> emp_id = '254'
>>> A = Employee('Jack', 'Rome', 23, 'M', emp_id)

答案 2 :(得分:1)

您必须将额外的init参数传递给超类init方法。

class Employee(Person):
    def __init__(self, emp_id, *args, **kwargs):
        self.emp_id = emp_id
        super().__init__(*args, **kwargs)

通过使用*args, **kwargs,子类会将所有未捕获的位置和命名参数传递给超类init方法。这意味着您不必指定父级所需的参数名称或所需的顺序。只需在父类的init方法中指定它即可。

答案 3 :(得分:0)

您对Employee的定义如下:

class Employee(Person):
    def __init__(self, emp_id):
        self.emp_id = emp_id

构造器(函数__init__()只有2个自变量(selfemp_id)。您可以创建一个传递名称,地点,年龄和性别的实例。

答案 4 :(得分:0)

您称该类为Employee,而不是Person,该人将采用4个参数,而Employee将仅采用一个参数。

创建的是Employee类的对象,而不是任何Person类。

    A = Employee(20)  # 20 is the emp_id.

尝试一下。

答案 5 :(得分:0)

您可以传递args和kwargs来容纳多个参数:

class Person:
    def __init__(self, name, place, age, sex):
        self.name = name
        self.place = place
        self.age = age
        self.sex = sex

class Employee(Person):
    def __init__(self, emp_id, *args, **kwargs):
        Person.__init__(self, *args, **kwargs)
        self.emp_id = emp_id

A = Employee(1111, 'Jack', 'Rome', 23, 'M')