我正在檢查這個問題以了解多重繼承,我被卡住了。 我怎樣才能設定從上一個類中繼承的物件的欄位呢?
class Vehicle()。
def __init__(self, name:str, seats:int) 。
self.name = name
self.seat = seats
def print_vehicle(self)。
print(f'Vehicle {self.name} has {self.seats} seats')
class Boat(Vehicle)。
def __init__(self, name:str, seats:int, engine_type:str) 。
super().__init__(name, seats)
self.engine_type = engine_type
def print_vehicle(self)。
print(f'Boat {self.name} has {self.seat} seats and engine {self.engine_type}'/span>)
class Car(Vehicle)。
def __init__(self, name:str, seats:int, fuel:str) 。
super().__init__(name, seats)
self.fuel = fuel
def print_vehicle(self)。
print(f'Car {self.name} has fuel {self.fuel}' )
class AnphibiousCar(船,汽車)。
def __init__(self, name, seats, engine_type, fuel)。
super(AnphibiousCar, self).__init__(name, seats, engine_type) # ??
def print_vehicle(self)。
print(f'Anphibious car {self.name} has {self. 座椅}和{self.engine_type} - {self.fuel}發動機')
ac = AnphibiousCar('name'/span>, 4, 'piston', 'gas')
ac.print_vehicle()
uj5u.com熱心網友回復:
重點是,每個類應該只關注屬于其直接責任的東西。其余的應該委托給超類(并且注意,當你用super()處理這種合作性繼承時。你的呼叫super()的方法應該不需要知道什么是實際的superclasses,特別是最近的一個--因為這可能會改變,取決于self的實際類別)。)
因此,讓我們重新實作你的類(在評論中做了一堆解釋):
class Vehicle。
# 添加了 "*, "標記,使 "name "和 "seats "成為*關鍵詞。
# 引數(即僅由其識別的引數)。
# *names*, never by their positions in a call's arguments list).。
def __init__(self, *, name: str, seats: int)。)
self.name = name
self.seat = seats
# We abstract out class-specific features into separate methods,/span>
# 在`print_vehicle()`方法中只保留常見的東西,。
# 這樣在子類中我們就只需要定制這些方法。
# (`list_features()`, `get_type_label()`), *not* `print_vehicle()`。
def print_vehicle(self)。
vehicle_type_label = self.get_type_label()
features = ', '.join(self.list_features())
print(f'{vehicle_type_label} {self.name}: {features}. ')
# Side note: the `list[str]` type annotation requires Python 3.9.
# 或更新的版本(為了與舊版本兼容,你需要
# 用`from typing import List'代替`List[str]').
def list_features(self) -> list[str] 。
return [f'has {self.seat} seats']
# 這個實作實際上是相當通用的(因此,
# 在大多數子類中,我們將*不需要定制它)。
def get_type_label(self) -> str:
return self.__class__.__name__。
class Boat(Vehicle)。
# 只有 "Boat "特定的引數(如上面所說的只有關鍵字的引數...)。
# 在這里被明確宣告。任何其他引數都被視為 "黑色"。
# box",只是被傳遞到超類中...。
def __init__(self, *, engine_type: str, **kwargs) 。
super().__init__(**kwargs)
self.engine_type = engine_type
# 這里我們只關注這個類的具體內容,處理。
# 其他的東西,盡可能的 "agnostically"...。
def list_features(self) -> list[str] 。
return super().list_features() [f'have {self.engine_type} engine']
class Car(Vehicle)。
# 并且類似地...。
def __init__(self, *, fuel: str, **kwargs) 。
super().__init__(**kwargs)
self.fuel = fuel
def list_features(self) -> list[str] 。
return super().list_features() [f'needs {self.fuel} fuel'/span>]
class AmphibiousCar(船,汽車)。
# Note: here we get our `__init__()` and `list_features()`.
# 是免費的(!),因為超類提供了我們所需要的一切。
# 當涉及到這兩個方法時。
# 我們可能要定制的唯一東西是:
def get_type_label(self) -> str:
return 'Amphibious car'。
ac = 兩棲汽車(
name='Julia-III',
seats=4,
engine_type='piston',
燃料='gas')
# "兩棲汽車Julia-III:有4個座位,需要氣體燃料,有活塞式發動機。"。
ac.print_vehicle()
作為進一步的閱讀,我推薦。https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
uj5u.com熱心網友回復:
你有一些錯誤:
你有一些錯誤。
super(AnphibiousCar, self).__init__(name, seats, engine_type)可以變成Boat.__init__(self, name, seats, engine_type)所以呼叫這個類時,你可以 提供關于如何初始化它的資訊。- 在
Boat中缺少一個引數,你應該給一個fuel引數 到超類Vehicle,像super().__init__(name, seats, "oil")
正如你可以注意到的,如果你使用super,你不需要傳遞self,如果你使用
類的名字,你就在使用它。
我的觀點是,是的,理解是好的,但不要浪費太多的 因為這種多重繼承只是理論上的,實際上在實際編碼中并不使用。 在實際編碼中沒有使用。事實上,這可能會造成很多混亂,并增加 冗長的模板... 例如,像Rust這樣的 "新 "語言,甚至不提供 繼承。 只是想說 "是的,研究它,但要保持簡單" ^_^
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/313131.html
標籤:
