2017-04-11 30 views
0

我試圖爲車輛路由問題複製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_typecapacitiesVehicle不直接從VehicleType繼承,我在Vehicle類中定義了add_capacity_dimension。這也違背了我的the docs瞭解有關__getattr__:當屬性查找一直沒有找到在 老地方(屬性

調用,即它不是一個實例屬性也不是在 類樹自我發現)。名稱是屬性名稱。

有人可以請解釋爲什麼實例van_type也受到影響嗎?

+0

這是什麼讓你感到驚訝?你感到驚訝的是'van_type'有一個'capacity'?你驚訝它發生了變異嗎? – user2357112

+0

@ user2357112你是對的,我錯過了看起來太長的鏈接。 'Vehicle'的'capacity'本身需要'__getattr__'。在這種情況下,唯一的方法是在'Vehicle'中定義'capacity',然後在其他屬性中使用'__getattr__'。 – roganjosh

+0

@roganjosh他們**將**匹配。如果他們不這樣做,那麼你的MCVE是錯誤的。 – wim

回答

2

Vehicle實例沒有「容量」屬性。

special_vanself.capacities屬性查找(從Vehicle.add_capacity_dimension實現內)解決不上Vehicle但對VehicleType,通過自定義__getattr__。因此,special_van.capacitiesvan_type.capacities是相同的字典。