Không có cách nào để "đặt lại" trình tạo. Tuy nhiên, bạn có thể sử dụng itertools.tee
để "sao chép" một trình lặp.
>>> z = zip(a, b)
>>> zip1, zip2 = itertools.tee(z)
>>> list(zip1)
[(1, 7), (2, 8), (3, 9)]
>>> list(zip2)
[(1, 7), (2, 8), (3, 9)]
Điều này liên quan đến giá trị bộ nhớ đệm, do đó, chỉ có ý nghĩa nếu bạn đang lặp qua cả hai lần lặp với cùng tốc độ. (Nói cách khác, không sử dụng nó theo cách tôi có ở đây!)
Cách tiếp cận khác là truyền xung quanh chức năng của máy phát và gọi nó bất cứ khi nào bạn muốn lặp lại nó.
def gen(x):
for i in range(x):
yield i ** 2
def make_two_lists(gen):
return list(gen()), list(gen())
Nhưng bây giờ bạn phải liên kết đối số với chức năng của trình tạo khi bạn truyền. Bạn có thể sử dụng lambda
cho điều đó, nhưng rất nhiều người tìm thấy lambda
xấu xí. (Không phải tôi mặc dù! YMMV.)
>>> make_two_lists(lambda: gen(10))
([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], [0, 1, 4, 9, 16, 25, 36, 49, 64, 81])
Tôi hy vọng điều đó sẽ không xảy ra nếu bạn tạo danh sách và sao chép nó.
Ngoài ra, như một cách tổng quát hơn để giải thích hành vi này, hãy xem xét điều này. Điểm của máy phát điện là tạo ra một loạt các giá trị, trong khi duy trì một số trạng thái giữa các lần lặp. Bây giờ, vào những thời điểm, thay vì chỉ đơn giản lặp lại trên một máy phát điện, bạn có thể muốn làm một cái gì đó như thế này:
z = zip(a, b)
while some_condition():
fst = next(z, None)
snd = next(z, None)
do_some_things(fst, snd)
if fst is None and snd is None:
do_some_other_things()
Hãy nói rằng vòng lặp này thể hoặc có thể không xả z
. Bây giờ chúng ta có một máy phát điện ở trạng thái không xác định! Vì vậy, điều quan trọng là tại thời điểm này, hành vi của một máy phát điện bị hạn chế theo một cách được xác định rõ ràng. Mặc dù chúng ta không biết máy phát ở đâu trong đầu ra, chúng ta biết rằng a) tất cả các truy cập tiếp theo sẽ tạo ra các giá trị sau trong chuỗi và b) khi nó "trống", chúng tôi đã nhận tất cả các mục trong chuỗi chính xác một lần. Càng có nhiều khả năng chúng ta phải thao túng trạng thái của z
, thì càng khó để giải thích về nó, vì vậy tốt nhất là chúng ta tránh các tình huống phá vỡ hai lời hứa đó.
Tất nhiên, như Joel Cornett chỉ ra bên dưới, nó là có thể viết máy phát điện chấp nhận tin nhắn qua phương thức send
; và nó sẽ có thể viết một máy phát điện có thể được thiết lập lại bằng cách sử dụng send
. Nhưng lưu ý rằng trong trường hợp đó, tất cả những gì chúng tôi có thể làm là gửi tin nhắn. Chúng ta không thể thao tác trực tiếp trạng thái của máy phát, và vì vậy tất cả các thay đổi đối với trạng thái của máy phát được xác định rõ (bởi chính bộ tạo - giả sử nó được viết chính xác!). send
thực sự là để thực hiện coroutines, vì vậy tôi sẽ không sử dụng nó cho mục đích này. Máy phát điện hàng ngày hầu như không bao giờ làm bất cứ điều gì với các giá trị được gửi đến chúng - Tôi nghĩ vì những lý do tôi đưa ra ở trên.
Hành vi của * máy phát *, không phải tất cả các lần lặp. Ví dụ, danh sách có thể lặp lại và bạn có thể gọi 'list (a) 'và nhận các bản sao của' a' nhiều như bạn muốn. –