Yield python là gì

Bài viết gốc:https://manhhomienbienthuy.bitbucket.io/2016/Jan/05/python-iterator-generator.html (đang xin phnghiền người sáng tác

*
)

Trong bài viết này, bọn họ đã khám phá một vài có mang khôn xiết phổ cập trong Pyhẹp mà lại cũng hay bị làm lơ cần hoàn toàn có thể dẫn đến những đọc sai nhất định. Những khái niệm kia chính là iterator và generator. Chúng được sử dụng liên tục cho nên việc hiểu nhằm sử dụng chúng cho và đúng là cực kỳ quan trọng.

Bạn đang xem: Yield python là gì

Iterator

Chúng ta có thể thực hiện vòng lặp for nhằm chăm bẵm qua những bộ phận của một list:

Có một số hàm dựng sẵn gồm Pybé được cho phép thao tác làm việc với hầu hết đối tượng người sử dụng này:

Giao thức interation

Những đối tượng người sử dụng "iterable" rất có thể được cẩn thận qua những phần tử, cũng chính vì chúng được cài đặt thủ tục __iter__. Phương thơm thức này đang trả về một đối tượng người sử dụng iterator. Đối tượng này cần phải hỗ trợ giao thức iteration (sẽ tiến hành kể tới sau). Nếu một đối tượng người sử dụng "iterable" có không ít loại thông qua thành phần khác nhau, hoàn toàn có thể bọn họ vẫn nên thêm các xử trí nhằm khẳng định iterator. (Ví dụ một thiết bị thị rất có thể chăm sóc theo chiều rộng cùng theo chiều sâu.)

Với đối tượng người tiêu dùng iterator, nó rất cần phải được cài đặt hai cách tiến hành sau, với cỗ nhì phương thức này được Điện thoại tư vấn là giao thức iteration.

Phương thơm thức __iter__ trả về bao gồm đối tượng người sử dụng iterator. Phương thơm thức này được trải nghiệm cài đặt cho cả đối tượng người dùng "iterable" cùng iterator để có thể áp dụng những câu lệnh for và in.Phương thơm thức __next__ (ở Pybé 2 là next) trả về bộ phận tiếp sau. Nếu không còn thành phần làm sao nữa thì StopIteration exception sẽ tiến hành raise.

Một hàm dựng sẵn của Pykhông lớn là iter nhấn đầu vào là một đối tượng người dùng "iterable" với trả về công dụng là một trong những iterator.

Chúng ta có thể trường đoản cú setup iterator là 1 class. ví dụ như dưới đây là một iterator hoạt động tương tự như hàm range có sẵn của Pythanh mảnh.

class yrange: def __init__(self, n): self.i = 0 self.n = n def __iter__(self): return self def __next__(self): if self.i Pmùi hương thức __iter__ đã có tác dụng đối tượng đổi thay đối tượng người sử dụng "iterable". Về thực chất, hàm iter sẽ Gọi mang lại cách thức __iter__ này của từng đối tượng người sử dụng.

Giá trị trả về của __iter__ là 1 trong những iterator. Nó cần phải có phương thức __next__ cùng phải trả về StopIteration giả dụ không còn phần test nào nữa.

Hãy test cùng với ví dụ trên:

class zrange: def __init__(self, n): self.n = n def __iter__(self): return zrange_iter(self.n)class zrange_iter: def __init__(self, n): self.i = 0 self.n = n def __iter__(self):# Iterators are iterables too# Adding this functions to lớn make them so return self def __next__(self): if self.i Iterator của Pyhẹp bao gồm một đặc điểm là nó chỉ có thể được ưng chuẩn qua một lần. Nên nếu đang chú tâm qua thành phần như thế nào rồi thì bạn bắt buộc chăm nom qua nó thêm lần làm sao nữa.

Vì đặc điểm trên, đề xuất nếu iterator với đối tượng người dùng "iterable" là một trong những, thì nó cũng chỉ hoàn toàn có thể triển khai iteration một lượt. Nhưng nếu bọn chúng chưa phải là một trong, thì bạn cũng có thể tiến hành từng nào lần tùy ý.

def yrange(n): i = 0 while i Mỗi lần lệnh yield được chạy, nó sẽ hiện ra một giá trị bắt đầu. (Vì cố gắng nó bắt đầu được hotline là generator)

Từ generator được áp dụng cho tất cả hàm (hàm generator là hàm đã nói sinh sống trên) và hiệu quả nhưng mà hàm đó ra đời (đối tượng được hàm generator hình thành cũng rất được hotline là generator). Vì vậy nhiều lúc việc này gây khó khăn đọc một ít.

Vậy một generator hoạt động như vậy nào? khi hàm generator được gọi, nó trả hiệu quả là 1 trong những đối tượng generator với ko thực thụ hotline với thực hiện hàm. Lúc thủ tục __next__ được Gọi, hàm generator vẫn bắt đầu chạy, cho tới khi nó gặp gỡ lệnh yield. Giá trị được yield sẽ tiến hành trả về mang đến hàm __next__.

lấy ví dụ dưới đây minc họa quá trình can dự thân yield cùng __next__ trong một đối tượng người sử dụng generator.

def integers(): """Infinite sequence of integers.""" i = 1 while True: yield i i = i + 1def squares(): for i in integers(): yield i * idef take(n, seq): """Returns first n values from the given sequence.""" seq = iter(seq) result = <> try: for i in range(n): result.append(seq.__next__()) except StopIteration: pass return resultprint(take(5, squares()))# prints <1, 4, 9, 16, 25>Biểu thức generatorBiểu thức generator là một trở thành thể của menu comprehension. Nó trông siêu giống như list comprehension tuy thế nó trả về một generator cố kỉnh bởi vì một danh sách.

Đơn giản hóa code

Đơn giản hóa code là một trong tác dụng của hàm và biểu thức generator. Để minc họa mang đến vấn đề này, họ vẫn mang một ví dụ cụ thể.

Chúng ta sẽ đối chiếu việc cài đặt hàm firstn (hàm trả về n số ngulặng không âm đầu tiên) với n có thể rất lớn và đưa sử rằng từng số bắt buộc một lượng bộ nhớ lưu trữ tương đối nhiều.

Thứ nhất, một bí quyết làm cho thường thì đó là thực hiện list:

def firstn(n): num, nums = 0, <> while num n: nums.append(num) num += 1 return numssum_of_first_n = sum(firstn(1000000))Đoạn code trên dễ dàng và dễ hiểu. Tất nhiên là nó vận động xuất sắc, ko kể một vấn đề bé dại là nó giữ toàn thể list vào bộ nhớ. Trong phần nhiều những ngôi trường hòa hợp, điều ấy là không giỏi Khi phải sử dụng cho dung lượng bộ nhớ Khủng mang lại vậy.

Xem thêm: Cây Hoa Hông Nhung - Hoa Hồng Cổ Nhung (Hồng Nhung Ta)

Bây giờ, bọn họ test áp dụng iterator. Dưới đó là một thiết đặt cho vấn đề này.

class firstn(object): def __init__(self, n): self.n = n self.num, self.nums = 0, <> def __iter__(self): return self def __next__(self): if self.num self.n: cur, self.num = self.num, self.num + 1 return cur else: raise StopIteration()sum_of_first_n = sum(firstn(1000000))Đoạn code trên đang hoạt động như chúng ta mong ước, tuy vậy nó bao gồm một số trong những sự việc như:

Có những chủng loại dựng sẵn được sử dụngLogic được diễn đạt một bí quyết phức tạpCode bắt đầu thừa nhiều năm chỉ nhằm thi công một iterator

Chúng ta hoàn toàn có thể áp dụng generator nhằm thi công iterator ngắn gọn gàng rộng. Chúng ta có thể thiết đặt nlỗi sau:

def firstn(n): num = 0 while num n: yield num num += 1sum_of_first_n = sum(firstn(1000000))Hàm firstn làm việc bên trên chỉ là một trong ví dụ minch họa. Pyhẹp có hàm dựng sẵn là range chuyển động tựa như điều đó. Tất nhiên là thực tế bọn họ nên sử dụng hàm dựng sẵn này.

Nâng cao hiệu suất

Việc sử dụng generator rất có thể nâng cấp năng suất bởi vì generator chỉ thực sự sinch kết quả Khi được Điện thoại tư vấn. Do đó, nó đang áp dụng ít bộ lưu trữ rộng. Ngoài ra, bọn họ không cần thiết phải hóng toàn bộ các thành phần của chính nó được hình thành không còn bắt đầu có thể áp dụng. Chúng sẽ tiến hành sinc trong quy trình chúng ta Call generator. Đây là các kết quả đạt được Khi bọn họ sử dụng iterator, mà lại generator là bí quyết nđính thêm gọn để tạo ra một iterator.

Để minh họa, họ vẫn so sánh nhị hàm dựng sẵn của Pynhỏ 2 là range với xrange.

Cả range với xrange gần như bộc lộ một khoảng chừng những số ngulặng. Tuy nhiên, range trả về một list còn xrange trả về một generator.

Bây giờ đồng hồ, họ công thêm tổng của một triệu số nguim không âm thứ nhất.

# using non-generatorsum_of_first_n = sum(range(1000000))# using generatorsum_of_first_n = sum(xrange(1000000))Hai cái code trông tương đối như là nhau. Tuy nhiên câu hỏi sử dụng range tốn bộ lưu trữ với thời gian rộng.

Lúc chúng ta sử dụng range, nó sẽ xây dựng danh mục 1 triệu bộ phận cùng tiếp nối tính tổng của bọn chúng. Việc này vô cùng tiêu tốn lãng phí bộ nhớ lưu trữ vì chưng bọn họ chỉ việc tính tổng của chúng mà lại thôi. Sự tiêu tốn lãng phí càng tăng thêm Khi con số bộ phận tăng lên cùng kích cỡ mỗi phần tử cũng to hơn.

Vì số đông tác dụng của generator cơ mà vào Pynhỏ bé 3, hàm range vận động như thể với xrange của Pynhỏ bé 2, có nghĩa là nó đã trả về generator chứ không phải là list.

Lưu ý điểm lưu ý của iterator là nó chỉ phê chuẩn sang 1 lần, cho nên việc sử dụng generator đang đem về hiệu quả ví như họ không mong muốn chăm chú nó nhiều hơn nữa 1 lần.

Hãy để ý ví dụ sau:

a = sum(xrange(1000000))p = product(xrange(1000000))Giả sử rằng vấn đề sinh một trong những khôn cùng tốn thời gian với bộ lưu trữ, thì trong ví dụ trên, bọn họ đang thực hiện các bước tốn kỉm này gấp đôi. Trong ngôi trường đúng theo này, vấn đề sử dụng menu với lưu giữ sẵn trong bộ nhớ lưu trữ có vẻ công dụng rộng.

nums = list(xrange(1000000))a = sum(nums)p = product(nums)Vì vậy việc chắt lọc sử dụng generator hay là không phụ thuộc nhiều vào thực tiễn yêu cầu của công việc. Nên bạn hãy suy xét và chọn lọc cảnh giác.

Itertools

Module itertools là thư viện chuẩn của Pynhỏ bé. Nó cung ứng cho chúng ta rất nhiều pháp luật để gia công bài toán với các iterator.

Trong nội dung bài viết này, họ sẽ điểm qua một vài hàm thú vui.

Xem thêm: 404 Not Found - Truyện Ngắn Tình Yêu Tuổi Học Trò : Mối Tình Đầu

chain sẽ gộp các iterator cùng nhau sinh sản thành một iterator.


Chuyên mục: Blogs