用于继承的Python类设计,具有不同数量的继承方法

时间:2018-04-20 13:08:04

标签: python-3.x inheritance multiple-inheritance

我正在为SOAP API构建Python API包装器。我需要设计一组API类,其中包含不同数量的动词操作(addgetlistremove等。此外,由于SOAP API中对象的性质,这些可能还包含来自(syncoptionsapplyrestart和{的子集的其他方法。 {1}})。每个动词的内部意味着极少数情况需要覆盖并且很容易被继承。我的问题是,某些端点是单例,或者出于任何原因可能只支持这些方法的子集。意思是:

EndpointA

    仅限
  • reset

EndpointB

  • getaddgetlist
  • removeapply

EndpointC

    仅限
  • restartadd

EndpointD

  • getaddgetlist
  • removeapplyrestart

我有超过100个端点。大多数人都有一个共同的主题:

  • resetaddgetlist

然而,有很多例外。

在我目前的设计中,所有端点都使用remove属性进行实例化,该属性控制线路上的SOAP连接,请求和响应。我正在寻找一种灵活创建类设计的方法,允许我在不需要复制代码或无意中继承API端点不支持的方法的情况下放入方法。

平坦的继承是有问题的,因为我没有足够的灵活性来处理方法的所有排列。

Client

我在想mixins,但正如你所看到的,动词方法依赖于普通客户端。根据我的理解,mixins应该只从BaseAPI(object): def __init___(self, client): self.client = client ChildAPI(BaseAPI): def __init___(self, client): super().__init__(client) def get(self, **kwargs): soap_method = methodcaller("".join(["get", self.__class__.__name__]), **kwargs) resp = soap_method(self.client.service) return resp def list(self, **kwargs): soap_method = methodcaller("".join(["list", self.__class__.__name__]), **kwargs) resp = soap_method(self.client.service) return stuff # same for add and remove... EndpointA(BaseAPI): def __init___(self, client): super().__init__(client) # now i have a problem as i only wanted the get method... EndpointD(BaseAPI): def __init___(self, client): super().__init__(client) # I have all the methods I wanted... 继承。

有人可以建议如何布置我的班级设计以尽可能地促进重复使用,并避免缺乏灵活性吗?

1 个答案:

答案 0 :(得分:1)

我是否理解,如果端点支持,方法的实现对于所有端点都是一样的?在这种情况下,您可以使用一个包含受支持的方法名称的小列表来解决它,并被每个Endpoint子类覆盖:

import functools

class BaseAPI:
    def __init___(self, client):
        self.client = client

class ChildAPI(BaseAPI):
    supported_methods = ["add", "get", "list", "remove", "apply", "restart", "reset"]

    @classmethod
    def assert_supported(cls, func):
        """Decorator looks up func's name in self.supported_methods."""
        @functools.wraps(func)
        def wrapper(self, *args, **kwargs):
            if func.__name__ not in self.supported_methods:
                raise AttributeError("This Endpoint does not support this method.")
            return func(self, *args, **kwargs)
        return wrapper

    # implementation of methods here, each decorated with @assert_supported
    @assert_supported
    def get(self, **kwargs):
        soap_method = methodcaller("".join(["get", self.__class__.__name__]), **kwargs)
        resp = soap_method(self.client.service)
        return resp

    @assert_supported
    def list(self, **kwargs):
        soap_method = methodcaller("".join(["list", self.__class__.__name__]), **kwargs)
        resp = soap_method(self.client.service)
        return stuff

class EndpointA(BaseAPI):
    supported_methods = ["get"]

class EndpointB(BaseAPI):
    supported_methods = ["add", "get", "list", "remove", "apply", "restart"]

class EndpointC(BaseAPI):
    supported_methods = ["add", "get"]

class EndpointD(BaseAPI):
    pass   # no change to supported_methods => all of them

这减少了将基本方法适应每个类一行的工作量,并且仍然可以灵活地添加所需的任何代码。