如何在Python中实现子类中抽象属性的ABC类定义

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

我有以下 abc 课程:

class Logger(ABC):
    @abstractproperty
    def filename_prefix(self):
        pass

    @abstractproperty
    def trace_id_length(self):
        pass

    @abstractproperty
    def run_id_length(self):
        pass

    def __init__(self):
        self._load_history()

    def _load_history(self):
        try:
            with open(
                os.path.join(trace_history_dir, f"{self.filename_prefix}_history.json"),
                "r",
            ) as f:
                history = json.load(f)
        except Exception as e:
            if e.__class__.__name__ == "FileNotFoundError":
                history = {"0".zfill(self.trace_id_length): "Init"}

                with open(
                    os.path.join(
                        trace_history_dir, f"{self.filename_prefix}_history.json"
                    ),
                    "w",
                ) as f:
                    json.dumps(history)
            else:
                raise e

        return history

还有以下子班:

class CostsLogger(Logger):
    def __init__(self):
        self.filename_prefix = filename_prefix
        self.trace_id_length = 4
        self.run_id_length = 4

        super.__init__()

问题是我在运行时遇到此错误:

Can't instantiate abstract class CostsLogger with abstract methods filename_prefix, run_id_length, trace_id_length

我不想强迫程序员在实现子类时使用

@property
,有什么办法可以避免吗?

python abstract-class
1个回答
0
投票

为了避免在子类中强制使用

@property
作为抽象属性,同时仍需要它们的实现,您可以修改抽象基类
Logger
以将
@abstractmethod
用于像
_define_attributes
这样的方法,该方法初始化必要的属性,例如
 filename_prefix
trace_id_length
run_id_length
。然后,子类(例如
CostsLogger
)可以在其
__init__
方法中或通过重写
_define_attributes
方法来定义这些属性:

from abc import ABC, abstractmethod
import os
import json

class Logger(ABC):
    def __init__(self):
        self._load_history()

    @abstractmethod
    def _define_attributes(self):
        # This method should set up the necessary attributes in the subclasses like self.filename_prefix, self.trace_id_length, self.run_id_length
        pass

    def _load_history(self):
        self._define_attributes()  # Ensure attributes are defined before use

        try:
            with open(
                os.path.join(trace_history_dir, f"{self.filename_prefix}_history.json"),
                "r",
            ) as f:
                history = json.load(f)
        except Exception as e:
            if e.__class__.__name__ == "FileNotFoundError":
                history = {"0".zfill(self.trace_id_length): "Init"}

                with open(
                    os.path.join(
                        trace_history_dir, f"{self.filename_prefix}_history.json"
                    ),
                    "w",
                ) as f:
                    json.dump(history, f)  # Should use json.dump() to write the object
            else:
                raise e

        return history

class CostsLogger(Logger):
    def __init__(self, filename_prefix, trace_history_dir):
        self.filename_prefix = filename_prefix
        self.trace_id_length = 4
        self.run_id_length = 4
        self.trace_history_dir = trace_history_dir  # Ensure trace_history_dir is available

        super().__init__()

    def _define_attributes(self):
        # Implementations for this method can be left empty if attributes are set in __init__
        pass

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