Python:子类中具有不同赋值的方法

ohfgkhjo  于 2023-01-01  发布在  Python
关注(0)|答案(1)|浏览(117)

我有一个子类中的方法run(),每个子类中有一个API POST请求,从POST请求中获取数据,并从该数据中分配一个ID给self._id,现在我也想获取一个描述,但是只有在SubClassB.run中的API请求self._api_obj.trigger(...)中返回描述。不在SubClassA.run中的API请求self._api_obj.trigger_run(...)中。对于SubclassA,我需要一个单独的API请求来获取描述。
我尝试了下面的方法,但是我不认为在SubClassB.run中分配2个属性,而在SubClassA.run中只分配1个属性是个好主意。对吗?因为根据我的理解,子类中的相同方法应该有相同的行为(只是不同的实现)。

class SuperClass:
    def __init__(self):
        self._id = None  # Assigned in run()
        self._description = None

    @property
    def description(self):
        raise NotImplementedError

    def run(self, *args):
        raise NotImplementedError

    @property
    def id(self):
        return self._id

class SubClassA(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj1()

    @property
    def description(self):
        if not self._description:
            _result = self._api_obj.get_data()
            self._description = _result["description"]
        return self._description

    def run(self, *args):
        _result = self._api_obj.trigger_run(foo="foo")
        self._id = _result["RunId"]

class SubClassB(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj2()

    @property
    def description(self):
        return self._description

    def run(self, *args):
        _result = self._api_obj.trigger(foo="foo", bar="bar", arg1="arg1", arg2="arg2")
        self._id = _result["data"]["id"]
        self._description = _result["data"]["description"]

有没有更好的方法来向self._description添加赋值?或者其他一些解决方案来包括描述?

3ks5zfa0

3ks5zfa01#

下面是我想到的解决方案:创建一个私有方法_run(),它将设置并返回运行的完整结果。方法SubClassB.get_description()将能够从中获得任何所需的信息。但是,SubClassA.get_description()将从API中获得描述。

class SuperClass:
    def __init__(self):
        self._id = None  # Assigned in run()
        self._run_result_info = None  # Assigned in _run()

    def _run(self, *args):
        raise NotImplementedError

    def run(self):
        raise NotImplementedError
    
    def get_description(self):
        raise NotImplementedError

    @property
    def id(self):
        return self._id

class SubClassA(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj1()

    def _run(self):
        self._run_result_info = self._api_obj.trigger_run(foo="foo")
        return self._run_result_info

    def run(self):
        _result = self._run()
        self._id = _result["RunId"]
        
    def get_description(self):
        _result = self._api_obj.get_data()
        _description = _result["description"]
        return _description

class SubClassB(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj2()

    def _run(self):
        self._run_result_info = self._api_obj.trigger(foo="foo", bar="bar", arg1="arg1", arg2="arg2")
        return self._run_result_info
    
    def run(self):
        _result = self._run()
        self._id = _result["data"]["id"]

    def get_description(self):
        return self._run_result_info["data"]["description"]

另一种选择:不保留运行的结果,因为它并不总是需要的。只要有一个属性description,它将通过API请求获得描述,只有在需要的情况下。这意味着我们将需要在SubClassB中的API请求来获得描述,而不是在SubClassB.run之后提供数据,但至少我们没有保留不需要的数据,如果没人要的话,我们只有在有人要的时候才保留

class SuperClass:
    def __init__(self):
        self._id = None  # Assigned in run()
        self._description = None

    @property
    def description(self):
        raise NotImplementedError

    def run(self):
        raise NotImplementedError

    @property
    def id(self):
        return self._id

class SubClassA(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj1()

    @property
    def description(self):
        if not self._description:
            _result = self._api_obj.get_data()
            self._description = _result["description"]
        return self._description

    def run(self, *args):
        _result = self._api_obj.trigger_run(foo="foo")
        self._id = _result["RunId"]

class SubClassB(SuperClass):
    def __init__(self):
        super().__init__()
        self._api_obj = ApiObj2()

    @property
    def description(self):
        if not self._description:
            _result = self._api_obj.get_info()
            self._description = _result["description"]
        return self._description

    def run(self, *args):
        _result = self._api_obj.trigger(foo="foo", bar="bar", arg1="arg1", arg2="arg2")
        self._id = _result["data"]["id"]

相关问题