Person.py
class Person:
def __init__(self, pname):
self.name = pname
@classmethod
def parse(cls, name):
return cls(name)
Employee.py
class Employee(Person):
def __init__(self, ename, esalary):
super().__init__(ename)
self.salary = esalary
@classmethod
def parse(cls, data):
person = super().parse(data["name"])
person.salary = data["salary"]
return person
Customer.py
class Customer(Person):
def __init__(self, ename, country):
super().__init__(ename)
self.country = country
@classmethod
def parse(cls, data):
person = super().parse(data["name"])
person.country = data["country"]
return person
main.py
emp_data = {
"name": "john",
"salary": 1000
}
emp = Employee.parse(emp_data)
print(type(emp))
print(emp.name)
print(emp.salary)
cust_data = {
"name": "peter",
"country": "USA"
}
cust = Customer.parse(cust_data)
print(type(cust))
print(cust.name)
print(cust.country)
错误
TypeError Traceback (most recent call last)
<ipython-input-32-a5abd51d9870> in <module>()
36 "salary": 1000
37 }
---> 38 emp = Employee.parse(emp_data)
39 print(type(emp))
40 print(emp.name)
<ipython-input-32-a5abd51d9870> in parse(cls, data)
14 @classmethod
15 def parse(cls, data):
---> 16 person = super().parse(data["name"])
17 person.salary = data["salary"]
18 return person
<ipython-input-32-a5abd51d9870> in parse(cls, name)
5 @classmethod
6 def parse(cls, name):
----> 7 return cls(name)
8
9 class Employee(Person):
TypeError: __init__() missing 1 required positional argument: 'esalary'
此示例仅用于在实际代码中重现问题。实际的解析函数涉及复杂的逻辑。
在上面的示例中,Employee
和Customer
类扩展了Person
类。根据错误,由init
调用Person
类的parse
方法构成同一个类,期待esalary
。但esalary
init方法上没有Person
属性。
我的计划有什么问题?我想我不理解继承。拜托,纠正我。首先,我是否正确构建了我的程序?
答案 0 :(得分:4)
您的问题是parse
调用cls(name)
,只有一个参数,但cls
是Employee
或Customer
,不一定是Person
}。您必须在施工时提供额外的参数(工资/国家/地区)(当您致电parse
时),或者在未提供时提供默认值。
通过parse
:
@classmethod
def parse(cls, name, *args, **kwargs):
return cls(name, *args, **kwargs)
允许你做类似的事情:
Employee.parse(name, salary) # Really no different than Employee(name, salary)
或者在子构造函数中为这些参数添加默认值,以便只使用名称构造它们:
class Customer(Person):
def __init__(self, ename, country=None):
# ...
class Employee(Person):
def __init__(self, ename, esalary=None):
# ...
请注意,这可能会导致您在这些属性中浮动None
个值,但如果您想构建一个新的Employee
对象并且不想提供这个值,则这是不可避免的同时支付工资。
答案 1 :(得分:3)
请考虑以下事项:
class Foo():
@classmethod
def p(cls):
print(cls.__name__)
class Bar(Foo):
@classmethod
def p(cls):
super().p()
bar = Bar()
bar.p()
这将打印&#34; Bar&#34;。从Foo.p
内部调用时传递给Bar.p
的类对象实际上是Bar
类,而不是Foo
类。
因此,在您的代码中,当您通过Person.parse
致电Employee.parse
时,Person.parse
,return cls(name)
中的行实际上正在调用Employee(name)
,但{{1}初始化需要2个位置参数。
要使您的代码使用此结构,您的Employee
必须具有相同的签名或至少兼容的签名(例如,通过向__init__
添加* args {s} { {1}}方法并将它们传递给构造函数)。