我有以下 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
,有什么办法可以避免吗?
为了避免在子类中强制使用
@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