Làm thế nào chính xác để hiểu máy phát điện hoạt động?


92

Sự hiểu biết của máy phát điện làm gì? Làm thế nào nó hoạt động? Tôi không thể tìm thấy một hướng dẫn về nó.


1
Để rõ ràng, tên ngôn ngữ cho những điều này là biểu thức của trình tạo , không phải là cách hiểu của trình tạo .
ShadowRanger

1
@ShadowRanger Có một cuộc thảo luận về danh sách gửi thư Python-dev vào tháng 7 năm 2018 về "Cú pháp hiểu tên" trong đó có một thỏa thuận dự kiến ​​nhưng khá nhất trí gọi chúng là "trình tạo hiểu" vì lợi ích nhất quán.
Aaron Hall

Câu trả lời:


145

Bạn có hiểu toàn bộ danh sách không? Nếu vậy, biểu thức trình tạo giống như một danh sách hiểu được, 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ó sẽ đợi và đưa ra từng mục ra khỏi biểu thức, từng mục 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 <genexpr> at 0x7f2ad75f89e0>
>>> 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.
... 
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # 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
>>> 

Bởi vì một biểu thức bộ tạo chỉ phải mang lại một mục tại một thời điểm, nó có thể dẫn đến tiết kiệm lớn trong việc sử dụng bộ nhớ. Biểu thức trình tạo có ý nghĩa nhất trong các tình huống mà bạn cần lấy từng mục một, thực hiện nhiều phép tính dựa trên mục đó, 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 một biểu thức trình tạo và lấy một vài giá trị cùng một lúc. 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ếp tục, hãy sử dụng cách hiểu danh sách để thay thế.


3
Một câu hỏi ở đây. Tôi đã sử dụng next (gen_name) để lấy kết quả và nó hoạt động trong Python 3. Có tình huống cụ thể nào mà chúng ta cần sử dụng __next __ () không?
Ankit Vashistha

3
@AnkitVashistha Không, luôn luôn sử dụng next(...)thay vì .__next__()bằng Python 3.
Todd Sewell

1
@gotgenes @AnkitVashistha If you need more than one value, you can also use a generator expression and grab a few at a time. Bạn có thể vui lòng cho một ví dụ về cách sử dụng này? Cảm ơn.
LittleZero

20

Khả năng hiểu của trình tạo là phiên bản lười biếng của khả năng hiểu danh sách.

Nó cũng giống như một sự hiểu danh sách ngoại trừ việc nó trả về một trình lặp thay vì danh sách, tức là một đối tượng có phương thức next () 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 tại đây và đối với máy phát điện xem tại đây .


4

Khả năng hiểu danh sách / trình tạo 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ừ danh sách hiện có.

Giả sử 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ể thực hiện việc 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 rangehàm không phải là 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 một trình tạo hoạt động tương tự, tôi có thể làm như sau:

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

Tuy nhiên, trong Python 3, rangelà một trình tạo, 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).


4
Cái này sai. Việc biểu thức bên ngoài có phải là bộ tạo hay không không liên quan gì đến việc liệu biểu thức bên trong có phải là. Mặc dù rõ ràng, thường không có nhiều điểm trong biểu thức trình tạo lấy các phần tử từ danh sách, bạn có thể làm điều đó.
Antimony

Điều này có thể được viết lại rõ ràng hơn? Tôi hiểu 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)
Lyndon trắng

3

Hiểu máy phát điện là một cách dễ dàng để tạo máy phát điện với một cấu trúc nhất định. Giả sử bạn muốn một generatorkết quả đầu ra lần lượt tất cả các số chẵn trong your_list. Nếu bạn tạo nó bằng cách sử dụng kiểu hàm, nó sẽ 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 biểu thức hiểu của trình tạo này:

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 sẽ nhận được số chẵn tiếp theo your_list.


0

Khả năng hiểu của trình tạo là một cách tiếp cận để tạo các tệp lặp, giống như một con trỏ di chuyển trên một 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 tải vào bộ nhớ cùng một lúc mà từng lần một. 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ớ.

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


-1

Một ví dụ khác về khả năng hiểu của Generator:

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 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.