2011-10-25 8 views
26

Tôi biết cách hoạt động của yield. Tôi biết hoán vị, nghĩ nó đơn giản như toán học.Nơi sử dụng năng suất bằng Python tốt nhất?

Nhưng lực thực sự của yield là gì? Khi nào tôi nên sử dụng? Một ví dụ đơn giản và tốt là tốt hơn.

+0

bản sao có thể có của [Từ khóa hiệu suất Python được giải thích] (http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained) – JBernardo

Trả lời

53

yield được sử dụng tốt nhất khi bạn có hàm trả về chuỗi và bạn muốn lặp qua chuỗi đó, nhưng bạn không cần phải có mọi giá trị trong bộ nhớ cùng một lúc.

Ví dụ, tôi có một tập lệnh python phân tích một danh sách lớn các tệp CSV và tôi muốn trả về mỗi dòng được xử lý trong một hàm khác. Tôi không muốn lưu trữ megabyte dữ liệu trong bộ nhớ cùng một lúc, vì vậy tôi yield mỗi dòng trong cấu trúc dữ liệu python. Vì vậy, các chức năng để có được dòng từ tập tin có thể giống như thế:

def get_lines(files): 
    for f in files: 
     for line in f: 
      #preprocess line 
      yield line 

sau đó tôi có thể sử dụng cú pháp giống như với danh sách này để truy cập vào đầu ra của chức năng này:

for line in get_lines(files): 
    #process line 

nhưng tôi tiết kiệm được nhiều dung lượng bộ nhớ.

+0

Trường hợp nào có 'yield' đến trong ví dụ này? – poplitea

+0

cảm ơn, tôi hơi bối rối. cho dòng trong f.readlines(): #process line làm tương tự. có vẻ như không cần phải mang lại lợi nhuận, hoặc là năng suất trong readall()? – whi

+0

Tôi đã thêm định nghĩa hàm thực tế để làm rõ điều này – murgatroid99

3

Sử dụng khác là trong ứng dụng khách mạng. Sử dụng 'năng suất' trong một chức năng của máy phát điện để xoay vòng qua nhiều ổ cắm mà không có sự phức tạp của các luồng.

Ví dụ: tôi có một ứng dụng thử nghiệm phần cứng cần gửi một máy bay R, G, B của hình ảnh đến phần mềm. Các dữ liệu cần thiết để được gửi trong lockstep: đỏ, xanh lá cây, xanh dương, đỏ, xanh lá cây, xanh dương. Thay vì đẻ trứng ba chủ đề, tôi đã có một máy phát điện đọc từ tập tin, mã hóa bộ đệm. Mỗi bộ đệm là một 'buf sản lượng'. Kết thúc tệp, hàm đã trả về và tôi đã kết thúc quá trình lặp lại.

Mã khách hàng của tôi lặp qua ba hàm máy phát, nhận bộ đệm cho đến khi kết thúc vòng lặp.

+0

cảm ơn. có '3 chủ đề + khóa' là không tốt. nhưng tại sao trong cùng một chủ đề chính? – whi

+0

Đơn giản. Kịch bản lệnh là một ứng dụng dòng lệnh nhỏ. Không có GUI. Ngoài ra, tất cả mọi thứ trong cùng một chủ đề có nghĩa là một lỗi trên một ổ cắm sẽ tắt toàn bộ máy khách. Vì tôi chỉ đang nói chuyện với một máy chủ, cái chết của một cái ổ cắm có nghĩa là tôi có thể nhanh chóng dừng tất cả các ổ cắm. –

15

Đơn giản chỉ cần đặt, yield cung cấp cho bạn một máy phát điện. Bạn sẽ sử dụng nó ở nơi bạn thường sử dụng một hàm return trong một hàm. Như một ví dụ thực sự giả tạo cắt và dán từ một dấu nhắc ...

>>> def get_odd_numbers(i): 
...  return range(1, i, 2) 
... 
>>> def yield_odd_numbers(i): 
...  for x in range(1, i, 2): 
...    yield x 
... 
>>> foo = get_odd_numbers(10) 
>>> bar = yield_odd_numbers(10) 
>>> foo 
[1, 3, 5, 7, 9] 
>>> bar 
<generator object yield_odd_numbers at 0x1029c6f50> 
>>> bar.next() 
1 
>>> bar.next() 
3 
>>> bar.next() 
5 

Như bạn có thể thấy, trong trường hợp đầu tiên foo nắm giữ toàn bộ danh sách trong bộ nhớ cùng một lúc. Nó không phải là một việc lớn đối với một danh sách với 5 yếu tố, nhưng nếu bạn muốn một danh sách 5 triệu? Không chỉ là một người ăn nhớ lớn, nó cũng tốn rất nhiều thời gian để xây dựng tại thời điểm hàm được gọi. Trong trường hợp thứ hai, bar chỉ cung cấp cho bạn một máy phát điện. Một máy phát là một vòng lặp - có nghĩa là bạn có thể sử dụng nó trong vòng lặp for, vv, nhưng mỗi giá trị chỉ có thể được truy cập một lần. Tất cả các giá trị cũng không được lưu trữ trong bộ nhớ cùng một lúc; đối tượng máy phát điện "ghi nhớ" nơi nó đang ở trong vòng lặp lần cuối bạn gọi nó - theo cách này, nếu bạn đang sử dụng số lần lặp lại (nói) lên tới 50 tỷ, bạn không phải tính đến 50 tỷ tất cả cùng một lúc và lưu trữ 50 tỷ con số để đếm qua. Một lần nữa, đây là một ví dụ khá giả tạo, bạn có thể sẽ sử dụng itertools nếu bạn thực sự muốn đếm đến 50 tỷ. :)

Đây là trường hợp sử dụng đơn giản nhất của máy phát điện. Như bạn đã nói, nó có thể được sử dụng để viết hoán vị hiệu quả, sử dụng yield để đẩy mọi thứ lên qua ngăn xếp cuộc gọi thay vì sử dụng một số loại biến ngăn xếp. Các máy phát điện cũng có thể được sử dụng cho việc di chuyển cây đặc biệt và tất cả các cách khác.

Tiếp tục đọc:

+2

Ví dụ thứ hai cũng giữ toàn bộ danh sách trong bộ nhớ cùng một lúc, vì nó cần giữ toàn bộ danh sách để quay lại trình tạo. – user2357112

1

Tôi đang đọc Cấu trúc dữ liệu và giải thuật bằng Python

Có một chức năng fabonacci sử dụng lợi nhuận. Tôi nghĩ đó là thời điểm tốt nhất để sử dụng năng suất.

def fibonacci(): 
    a, b = 0, 1 
    while True: 
     yield a 
     a, b = b, a+b 

bạn có thể sử dụng như thế này:

f = fibonacci() 
for i, f in enumerate(f): 
    print i, f 
    if i >= 100: break 

Vì vậy, tôi nghĩ, có lẽ, khi các yếu tố tiếp theo là tùy thuộc vào các yếu tố trước đây, đó là thời gian để sử dụng năng suất.