这是我使用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
我在做什么错了?
答案 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')
。对于类Employee
,Employee.__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
如果您希望Employee
像Person
一样初始化,则必须这样明确地说:
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个自变量(self
和emp_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')