最低Python版本:Python3.7
我正在编写一些代码来从版本化的json/yaml模式中编码/解码模型。我正在寻找一种干净的方法来实现这一点,这并不是一吨庞大的if-elif-elif链,用于测试模式版本。
所以,考虑到这样的情况:
class SchemaVersion(Enum):
v1 = "2020-10-15"
v2 = "2021-07-06"
v3 = "2022-01-10"
... etc我目前正在编写如下代码:
class Decodable(ABC, Generic[T]]):
@abstractmethod
@staticmethod
def decode(*, version: SchemaVersion, model: Dict[str, Any]) -> T:
# Factory pattern
# Decode a model given as dictionaries as per the schema version
pass
class Example(Decodable["Example"], Encodable)
@staticmethod
def decode(*, version: SchemaVersion, model: Dict[str, Any]) -> Example:
if version in (SchemaVersion.v1,SchemaVersion.v2):
... decode model using schema v1 (which is the same as v2 for this model)
elif version in (SchemaVersion.v3,):
... decode model using schema v3
else:
raise RuntimeError(...)我可以看到,随着对模式增加更多的修订,解码和编码的实现是巨大的,if/elif/else链是如何实现的。
我希望能够在模型类中修饰方法,以便基类上的泛型decode()静态方法可以根据正在解码的模式版本路由到派生类中的适当的解码器静态方法。这个是可能的吗?多么?
例如:
class Decodable:
@staticmethod
def decode(*, version: SchemaVersion, mdoel: Dict[str, Any]) -> Decodable:
... select the derived-class method decorated to decode the schema version and run it
class Example(Decodable, Encodable):
@decodes(SpecificationVersion.v1)
@decodes(SpecificationVersion.v2)
def _decode_0(*, version: SchemaVersion, model: Dict[str, Any]) -> Example:
.. decode. Note: schema v1 is the same as v2 for this model
@decodes(SpecificationVersion.v3)
def _decode_1(*, version: SchemaVersion, model: Dict[str, Any]) -> Example:
... decode因此,调用Example.decode(version=SchemaVersion.v1, model=...)会导致调用Example._decode_0(version=SchemaVersion.v1, model=...)。
谢谢!
发布于 2022-02-04 21:09:17
您想知道的答案是,我想是参数化的装饰师,它构建如下:
def decodes(versions: List[SpecificationSchema]):
def decorator(func):
def wrapper(self, version, *args, **kwargs):
# you can add and then update if already exist a hidden dict
# which will map a version to a callable function
return wrapper
return decorator使用将是
@decodes([SpecificationSchema.v1, SpecificationSchema.v2])
def decoder_1(...):
...如果您通过映射一个可调用的代码来创建一个数据集,那么解码将是这样的
def decode(version, ...):
return self.decode_for_version[version]()https://stackoverflow.com/questions/70992475
复制相似问题