我試圖爲車輛路由問題複製Java庫的API,並突出顯示了某些我不瞭解Python類的內容。__getattr__意外地更新了非繼承類的實例
車隊可以分爲兩個基本標準;第一種是您擁有的車輛類型(例如定義運力,運行成本等的VehicleType
)以及具有不同換檔模式的單獨車輛(Vehicle
等)。
在我的簡化示例中,我想定義一個VehicleType
,然後單個Vehicle
,它將傳遞給構造函數的VehicleType
的屬性。在Lennart here的回答下,使用__getattr__
在一般情況下完美地工作。但是,想象一下,我有一輛滿載50輛汽車的駕駛員,因爲他具有攜帶危險物品的特殊資格,所以我想在實例上添加額外的容量屬性。我試過如下:
class VehicleType(object):
def __init__(self, fixed_cost=0, cost_per_distance=0, cost_per_time=0):
self.capacities = {}
self.fixed_cost = fixed_cost
self.cost_per_distance = cost_per_distance
self.cost_per_time = cost_per_time
def add_capacity_dimension(self, dimension_id, dimension_size):
""" Define a package type and how many of them this vehicle type can carry """
self.capacities[dimension_id] = dimension_size
class Vehicle(object):
def __init__(self, vehicle_type=None, identifier=None):
self._vehicle_type = vehicle_type
self.identifier = identifier
def add_capacity_dimension(self, dimension_id, dimension_size):
self.capacities[dimension_id] = dimension_size
def __getattr__(self, name):
return getattr(self._vehicle_type, name)
if __name__ == '__main__':
van_type = VehicleType()
van_type.add_capacity_dimension("general items", 34)
special_van = Vehicle(vehicle_type=van_type)
special_van.add_capacity_dimension("hazardous chemicals", 50)
print("Capacities of special van: {}".format(special_van.capacities))
print("Capacity of van_type: {}".format(van_type.capacities)) # Why?
我不明白爲什麼我的做法也影響了van_type
的capacities
。 Vehicle
不直接從VehicleType
繼承,我在Vehicle
類中定義了add_capacity_dimension
。這也違背了我的the docs瞭解有關__getattr__
:當屬性查找一直沒有找到在 老地方(屬性
調用,即它不是一個實例屬性也不是在 類樹自我發現)。名稱是屬性名稱。
有人可以請解釋爲什麼實例van_type
也受到影響嗎?
這是什麼讓你感到驚訝?你感到驚訝的是'van_type'有一個'capacity'?你驚訝它發生了變異嗎? – user2357112
@ user2357112你是對的,我錯過了看起來太長的鏈接。 'Vehicle'的'capacity'本身需要'__getattr__'。在這種情況下,唯一的方法是在'Vehicle'中定義'capacity',然後在其他屬性中使用'__getattr__'。 – roganjosh
@roganjosh他們**將**匹配。如果他們不這樣做,那麼你的MCVE是錯誤的。 – wim