【发布时间】:2022-01-20 21:27:03
【问题描述】:
我有以下课程,其中:
iterable 是传递的参数,例如range(20),n_max 是一个可选值,它限制缓存应具有的元素数量,iterator 是一个使用可迭代对象启动的字段, cache 是我要填充的列表,finished 是 bool,它表示迭代器是否为“空”。这是一个示例输入:
>>> iterable = range(20)
>>> cachedtuple = CachedTuple(iterable)
>>> print(cachedtuple[0])
0
>>> print(len(cachedtuple.cache))
1
>>> print(cachedtuple[10])
10
>>> print(len(cachedtuple.cache))
11
>>> print(len(cachedtuple))
20
>>> print(len(cachedtuple.cache))
20
>>> print(cachedtuple[25])
@dataclass
class CachedTuple:
iterable: Iterable = field(init=True)
n_max: Optional[int] = None
iterator: Iterator = field(init=False)
cache: list = field(default_factory=list)
finished: bool = False
def __post_init__(self):
self.iterator = iter(self.iterable)
def cache_next(self):
if self.n_max and self.n_max <= len(self.cache):
self.finished = True
else:
try:
nxt = next(self.iterator)
self.cache.append(nxt)
except StopIteration:
self.finished = True
def __getitem__(self, item: int):
match item:
case item if type(item) != int:
raise IndexError
case item if item < 0:
raise IndexError
case item if self.finished or self.n_max and item > self.n_max:
raise IndexError(f"Index {item} out of range")
case item if item >= len(self.cache):
while item - len(self.cache) >= 0:
self.cache_next()
return self.__getitem__(item)
case item if item < len(self.cache):
return self.cache[item]
def __len__(self):
while not self.finished:
self.cache_next()
return len(self.cache)
虽然这段代码肯定不好,但至少它适用于几乎所有场景,但以 Python 的 range 函数为例。如果我使用例如
cachedtuple = CachedTuple(range(20))
for element in cachedtuple:
print(element)
我得到元素直到19,然后程序无限循环。我认为一个问题可能是我的代码中没有raise StopIteration。所以我有点迷失如何解决这个烂摊子。
【问题讨论】:
-
我一定要问,match语句的意义何在?
标签: python caching python-dataclasses