我有這個代碼:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, name, last_name, age, indexNr, notes):
super().__init__(name, last_name, age)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, name, last_name, age, salary, position):
super().__init__(name, last_name, age)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
Student.__init__(name, last_name, age, indexNr, notes)
Employee.__init__(name, last_name, age, salary, position)
我想像這樣創建一個 WorkingStudent 實體:
ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
但它不起作用,我收到此錯誤:
TypeError: __init__() missing 1 required positional argument: 'notes'
或者我在這里做錯了什么?另外,我已經super()
在 WorkingStudent 類中嘗試過,但它只呼叫第一個傳遞類的建構式。即在這種情況下Student
注意:我已經經歷了多個 StackOverflow 查詢,但我找不到任何可以回答這個問題的東西。(或者也許我錯過了)。
uj5u.com熱心網友回復:
代替顯式類,用于super()
沿 mro 傳遞引數:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
# since Employee comes after Student in the mro, pass its arguments using super
super().__init__(name, last_name, age, salary, position)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, name, last_name, age, salary, position):
super().__init__(name, last_name, age)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
# pass all arguments along the mro
super().__init__(name, last_name, age, indexNr, notes, salary, position)
# uses positional arguments
ws = WorkingStudent("john", "brown", 18, 1, [1,2,3], 1000, 'Programmer')
# then you can print stuff like
print(f"My name is {ws.name} {ws.last_name}. I'm a {ws.position} and I'm {ws.age} years old.")
# My name is john brown. I'm a Programmer and I'm 18 years old.
檢查先生:
WorkingStudent.__mro__
(__main__.WorkingStudent,
__main__.Student,
__main__.Employee,
__main__.Person,
object)
當你創建一個 WorkingStudent 的實體時,最好傳遞關鍵字引數,這樣你就不必擔心弄亂引數的順序。
由于 WorkingStudent 將屬性的定義推遲到父類,因此立即將所有引數傳遞給層次結構,super().__init__(**kwargs)
因為子類不需要知道它不處理的引數。第一個父類是 Student,所以 self.IndexNr 等在那里定義。mro 中的下一個父類是 Employee,因此從 Student 中,將剩余的關鍵字引數傳遞給它,super().__init__(**kwargs)
再次使用。從 Employee 開始,定義在那里定義的屬性,然后super().__init__(**kwargs)
再次通過 mro(到 Person)傳遞其余的屬性。
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, indexNr, notes, **kwargs):
# since Employee comes after Student in the mro, pass its arguments using super
super().__init__(**kwargs)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, salary, position, **kwargs):
super().__init__(**kwargs)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, **kwargs):
# pass all arguments along the mro
super().__init__(**kwargs)
# keyword arguments (not positional arguments like the case above)
ws = WorkingStudent(name="john", last_name="brown", age=18, indexNr=1, notes=[1,2,3], salary=1000, position='Programmer')
uj5u.com熱心網友回復:
問題:對于最派生的類,我們有很多引數,需要用于初始化所有基類。但是,在 Python 的多繼承系統 withsuper()
中,接下來要初始化的類取決于可能已經在另一個類中確定的 MRO(方法決議順序)。因此,當我們使用多重繼承時,我們不知道在使用時會__init__
呼叫哪個類super()
。
解決方案:為引數使用一致的名稱,然后利用**kwargs
,以便每個類接受它關心的(顯式命名的)引數,并轉發其余的。
看起來像:
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, indexNr, notes, **kwargs):
super().__init__(**kwargs)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, salary, position, **kwargs):
super().__init__(**kwargs)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, **kwargs):
super().__init__(**kwargs)
強制客戶端代碼使用關鍵字引數對客戶端來說是更多的作業,但它也有助于防止錯誤位置引數的順序錯誤。
uj5u.com熱心網友回復:
這似乎可行,但并不美觀。我承認我對 Python 中的多重繼承并不熟悉,我認為這可能不是最正確的方式。希望其他人能給出更好的答案。
class Person:
def __init__(self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
class Student(Person):
def __init__(self, name, last_name, age, indexNr, notes):
Person.__init__(self, name, last_name, age)
self.indexNr = indexNr
self.notes = notes
class Employee(Person):
def __init__(self, name, last_name, age, salary, position):
Person.__init__(self, name, last_name, age)
self.salary = salary
self.position = position
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
Student.__init__(self, name, last_name, age, indexNr, notes)
Employee.__init__(self, name, last_name, age, salary, position)
ws = WorkingStudent("john", "brown", 18, 1, [1, 2, 3], 1000, 'Programmer')
print(ws)
輸出:
<__main__.WorkingStudent object at 0x000002526F11F3D0>
uj5u.com熱心網友回復:
這是實作目標的最簡單方法。
如果您的 WorkingStudent 類像這樣繼承 Student 和 Employee 類,
class WorkingStudent(Student, Employee):
def __init__(self, name, last_name, age, indexNr, notes, salary, position):
Student.__init__(self, name, last_name, age, indexNr, notes)
Employee.__init__(self, name, last_name, age, salary, position)
ws = WorkingStudent("john", "brown", 18, 1, [1, 2, 3], 1000, 'Programmer')
print(ws)
print(ws.name)
print(ws.age)
你的輸出將是......
輸出:
<位于 0x7fc6c4d8ba10 的主.WorkingStudent 物件>
john
18
[1, 2, 3]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/478557.html