import itertools
class Indexable(object):
def __init__(self,it):
self.it = iter(it)
def __iter__(self):
return self.it
def __getitem__(self,index):
try:
return next(itertools.islice(self.it,index,index+1))
except TypeError:
return list(itertools.islice(self.it,index.start,index.stop,index.step))
Bạn có thể sử dụng nó như thế này:
it = Indexable(fib())
print(it[10])
#144
print(it[2:12:2])
#[610, 1597, 4181, 10946, 28657]
ý rằng it[2:12:2]
không trả lại [3, 8, 21, 55, 144]
kể từ khi iterator đã tiến 11 yếu tố vì cuộc gọi đến it[10]
.
Edit: Nếu bạn muốn it[2:12:2]
trở [3, 8, 21, 55, 144]
thì có lẽ sử dụng này để thay thế:
class Indexable(object):
def __init__(self, it):
self.it = iter(it)
self.already_computed = []
def __iter__(self):
for elt in self.it:
self.already_computed.append(elt)
yield elt
def __getitem__(self, index):
try:
max_idx = index.stop
except AttributeError:
max_idx = index
n = max_idx - len(self.already_computed) + 1
if n > 0:
self.already_computed.extend(itertools.islice(self.it, n))
return self.already_computed[index]
phiên bản này giúp tiết kiệm các kết quả trong self.already_computed
và sử dụng những kết quả nếu có thể. Nếu không, nó tính toán nhiều kết quả hơn cho đến khi nó có đủ số để trả về phần tử hoặc lát được lập chỉ mục.
Triển lãm các hành vi tương tự như một danh sách, __getitem__ sẽ cần phải tua máy phát điện. Có cách nào dễ dàng để làm điều đó không? –
Tôi không biết nếu có cách nào để làm điều đó, dễ dàng hay không, nhưng lớp Indexable chỉ có thể lưu trữ tất cả các mục đã tạo ra trong một danh sách. Sau đó '__getitem__' sẽ kéo các số trực tiếp từ danh sách, sau khi đầu tiên tiến hành bộ tạo nếu cần thiết. – MatrixFrog
Cảm ơn MatrixFrog; đó là những gì tôi đã làm. – unutbu