首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过装饰器将调用路由到静态方法?

如何通过装饰器将调用路由到静态方法?
EN

Stack Overflow用户
提问于 2022-02-04 20:25:56
回答 1查看 35关注 0票数 -1

最低Python版本:Python3.7

我正在编写一些代码来从版本化的json/yaml模式中编码/解码模型。我正在寻找一种干净的方法来实现这一点,这并不是一吨庞大的if-elif-elif链,用于测试模式版本。

所以,考虑到这样的情况:

代码语言:javascript
复制
class SchemaVersion(Enum):
    v1 = "2020-10-15"
    v2 = "2021-07-06"
    v3 = "2022-01-10"
    ... etc

我目前正在编写如下代码:

代码语言:javascript
复制
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()静态方法可以根据正在解码的模式版本路由到派生类中的适当的解码器静态方法。这个是可能的吗?多么?

例如:

代码语言:javascript
复制
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=...)

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2022-02-04 21:09:17

您想知道的答案是,我想是参数化的装饰师,它构建如下:

代码语言:javascript
复制
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

使用将是

代码语言:javascript
复制
@decodes([SpecificationSchema.v1, SpecificationSchema.v2])
def decoder_1(...):
    ...

如果您通过映射一个可调用的代码来创建一个数据集,那么解码将是这样的

代码语言:javascript
复制
def decode(version, ...):
    return self.decode_for_version[version]()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70992475

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档