派生类如何使用基类的映射方法?

问题描述 投票:0回答:2

想象一下我在 python 中有以下内容(实际语言并不重要,因为我在其他语言(如 php)中也遇到了问题。基类“CarModel”和来自“CarModel”的派生类“TruckModel”。

class CarModel:
    def __init__(self):
        self.__wheel_count: int = 0

    def set_wheel_count(self, value: int) -> None:
        self.__wheel_count = value

class TruckModel(CarModel):
    def __init__(self):
        super().__init__()
        self.__load_in_kg: int = 0

    def set_load_in_kg(self, value: int) -> None:
        self.__load_in_kg= value

如果我现在有一个映射类,它应该转换为例如我的模型的字典,如何为我的派生类重用映射方法? 特别是如果我有一个包含很多 setter 方法的基类,我必须重复代码,这是我不喜欢的(“干”)。

class VehicleMapper:
    def map_car_dict_to_car_model(dict: Dict) -> CarModel:
        model: CarModel = CarModel()
        model.set_wheel_count(dict['wheelCount'])
        return model

    def map_truck_dict_to_truck_model(dict: Dict) -> TruckModel:
        model: TruckModel= TruckModel()
        model.set_load_in_kg(dict['loadInKg'])
 
        model.set_wheel_count(dict['wheelCount']) #  ??? How can I re-use the map-method for the base class here ???
        
        return model

我可以将映射方法移至模型类,这样就可以了。但我被告知,模型类应该只“保存”数据,而不应该做任何事情。这就是为什么有映射器类,对吗?

python types orm mapping derived-class
2个回答
1
投票

更干净、更可靠的方法是使用单独的映射器/工厂。而且更合理,因为在您的情况下,您还需要从字典键到相应模型属性名称的可配置映射。
考虑以下模式:

class CarModel: def __init__(self): self.__wheel_count: int = 0 def wheel_count(self, value: int) -> None: self.__wheel_count = value wheel_count = property(None, wheel_count) class TruckModel(CarModel): def __init__(self): super().__init__() self.__load_in_kg: int = 0 def load_in_kg(self, value: int) -> None: self.__load_in_kg= value load_in_kg = property(None, load_in_kg) class VehicleFactory: """Vehicle base factory""" __model__ = None __map_keys__ = None @classmethod def create(cls, data): model = cls.__model__() for k, attr in cls.__map_keys__.items(): setattr(model, attr, data[k]) return model class CarFactory(VehicleFactory): __model__ = CarModel __map_keys__ = {'wheelCount': 'wheel_count'} class TruckFactory(VehicleFactory): __model__ = TruckModel __map_keys__ = {'wheelCount': 'wheel_count', 'loadInKg': 'load_in_kg'}

用途:

car = CarFactory.create({'wheelCount': 4}) print(vars(car)) # {'_CarModel__wheel_count': 4} truck = TruckFactory.create({'wheelCount': 4, 'loadInKg': 500}) print(vars(truck)) # {'_CarModel__wheel_count': 4, '_TruckModel__load_in_kg': 500}



0
投票

class CarModel: mapping = {} @staticmethod def _key(key, mapping=mapping): def decorator(func): mapping[key] = func return decorator @classmethod def from_dict(cls, d: dict): instance = cls() for key, value in d.items(): cls.mapping[key](instance, value) return instance def __init__(self): self.__wheel_count: int = 0 @_key('wheelCount') def set_wheel_count(self, value: int) -> None: self.__wheel_count = value class TruckModel(CarModel): def __init__(self): super().__init__() self.__load_in_kg: int = 0 @CarModel._key('loadInKg') def set_load_in_kg(self, value: int) -> None: self.__load_in_kg= value

这样:

print(vars(CarModel.from_dict({'wheelCount': 4}))) print(vars(TruckModel.from_dict({'wheelCount': 6, 'loadInKg': 8000})))

输出:

{'_CarModel__wheel_count': 4} {'_CarModel__wheel_count': 6, '_TruckModel__load_in_kg': 8000}

演示:
https://ideone.com/xp2IAB

© www.soinside.com 2019 - 2024. All rights reserved.