2008-12-13 32 views

Trả lời

94

Bạn có hiểu hiểu danh sách không? Nếu vậy, một biểu thức máy phát điện giống như một danh sách hiểu, nhưng thay vì tìm tất cả các mục bạn quan tâm và đóng gói chúng vào danh sách, nó chờ đợi, và sản lượng mỗi mục ra khỏi biểu thức, từng người một.

>>> my_list = [1, 3, 5, 9, 2, 6] 
>>> filtered_list = [item for item in my_list if item > 3] 
>>> print filtered_list 
[5, 9, 6] 
>>> len(filtered_list) 
3 
>>> # compare to generator expression 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> print filtered_gen # notice it's a generator object 
<generator object at 0xb7d5e02c> 
>>> len(filtered_gen) # So technically, it has no length 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'generator' has no len() 
>>> # We extract each item out individually. We'll do it manually first. 
... 
>>> filtered_gen.next() 
5 
>>> filtered_gen.next() 
9 
>>> filtered_gen.next() 
6 
>>> filtered_gen.next() # Should be all out of items and give an error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> # Yup, the generator is spent. No values for you! 
... 
>>> # Let's prove it gives the same results as our list comprehension 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> gen_to_list = list(filtered_gen) 
>>> print gen_to_list 
[5, 9, 6] 
>>> filtered_list == gen_to_list 
True 
>>> 

Do biểu thức trình tạo chỉ phải mang lại một mục tại một thời điểm nên có thể tiết kiệm lớn khi sử dụng bộ nhớ. Biểu thức máy phát điện có ý nghĩa nhất trong các tình huống mà bạn cần thực hiện một mục tại một thời điểm, thực hiện nhiều phép tính dựa trên mục đó và sau đó chuyển sang mục tiếp theo. Nếu bạn cần nhiều hơn một giá trị, bạn cũng có thể sử dụng biểu thức trình tạo và lấy một vài lần tại một thời điểm. Nếu bạn cần tất cả các giá trị trước khi chương trình của bạn tiến hành, thay vào đó hãy sử dụng tính năng đọc danh sách.

12

Đọc hiểu máy phát là phiên bản lười biếng của việc hiểu danh sách.

Nó giống như một danh sách hiểu ngoại trừ nó trả về một trình lặp thay vì danh sách tức là một đối tượng với một phương thức tiếp theo() sẽ mang lại phần tử tiếp theo.

Nếu bạn không quen với việc hiểu danh sách, hãy xem here và dành cho máy phát, xem here.

4

List/generator comprehension là một cấu trúc mà bạn có thể sử dụng để tạo danh sách/trình tạo mới từ một danh sách hiện có.

Hãy nói rằng bạn muốn tạo danh sách các ô vuông của mỗi số từ 1 đến 10. Bạn có thể làm điều này bằng Python:

>>> [x**2 for x in range(1,11)] 
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 

đây, range(1,11) tạo danh sách [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], nhưng range chức năng không phải là một trình tạo trước Python 3.0, và do đó cấu trúc tôi đã sử dụng là một danh sách hiểu.

Nếu tôi muốn tạo ra một máy phát điện mà làm điều tương tự, tôi có thể làm điều đó như thế này:

>>> (x**2 for x in xrange(1,11)) 
<generator object at 0x7f0a79273488> 

Trong Python 3, tuy nhiên, range là một máy phát điện, vì vậy kết quả chỉ phụ thuộc vào cú pháp bạn sử dụng (dấu ngoặc vuông hoặc dấu ngoặc tròn).

+1

này là sai. Cho dù biểu thức bên ngoài là một máy phát điện không có gì để làm với biểu thức bên trong là. Mặc dù rõ ràng, thường không có nhiều điểm trong một biểu thức máy phát điện lấy các yếu tố từ một danh sách, bạn có thể làm điều đó. – Antimony

+0

Điều này có thể viết lại rõ ràng hơn không? Tôi nhận được những gì bạn đang nói, nhưng như Antimony nói, có vẻ như bạn đang nói điều gì đó khác. (và điều có vẻ như bạn đang nói là sai) –

2

Đọc hiểu máy phát điện là cách dễ dàng để tạo máy phát điện với cấu trúc nhất định. Giả sử bạn muốn có một generator kết quả đầu ra từng cái một, tất cả các số chẵn trong your_list. Nếu bạn tạo ra nó bằng cách sử dụng chức năng tạo kiểu cho nó sẽ là như thế này:

def allEvens(L): 
    for number in L: 
     if number % 2 is 0: 
      yield number 

evens = allEvens(yourList) 

Bạn có thể đạt được kết quả tương tự với điều này biểu hiện phát hiểu:

evens = (number for number in your_list if number % 2 == 0) 

Trong cả hai trường hợp, khi bạn gọi next(evens) bạn lấy số chẵn tiếp theo trong your_list.

0

Đọc hiểu máy phát điện là một cách tiếp cận để tạo vòng lặp, giống như con trỏ di chuyển trên tài nguyên. Nếu bạn biết con trỏ mysql hoặc con trỏ mongodb, bạn có thể biết rằng toàn bộ dữ liệu thực tế không bao giờ được nạp vào bộ nhớ cùng một lúc, nhưng mỗi lần một con trỏ. Con trỏ của bạn di chuyển qua lại, nhưng luôn có một phần tử hàng/danh sách trong bộ nhớ.

Tóm lại, bằng cách sử dụng máy phát, bạn có thể dễ dàng tạo các con trỏ trong python.

0

Một ví dụ khác Generator hiểu:

print 'Generator comprehensions' 

def sq_num(n): 
    for num in (x**2 for x in range(n)):  
     yield num 

for x in sq_num(10): 
    print x 
Các vấn đề liên quan