*
)

Trong nội dung bài viết này, họ vẫn tò mò một vài khái niệm vô cùng thịnh hành vào Pythanh mảnh nhưng cũng hay bị bỏ lỡ cần hoàn toàn có thể dẫn đến các gọi không nên nhất quyết. Những khái niệm đó chính là iterator với generator. Chúng được sử dụng tiếp tục nên việc đọc để sử dụng chúng đến và đúng là cực kỳ quan trọng.

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

Iterator

Chúng ta có thể áp dụng vòng lặp for để coi sóc qua các phần tử của một list:

Có một số trong những hàm dựng sẵn gồm Pyhẹp được cho phép làm việc với phần nhiều đối tượng người sử dụng này:

Giao thức interation

Những đối tượng người dùng "iterable" rất có thể được lưu ý qua những phần tử, bởi vì chúng được setup cách tiến hành __iter__. Pmùi hương thức này đã trả về một đối tượng người tiêu dùng iterator. Đối tượng này cần phải cung ứng giao thức iteration (sẽ được kể tới sau). Nếu một đối tượng người dùng "iterable" có không ít kiểu chăm nom bộ phận khác biệt, có thể bọn họ sẽ cần thêm những xử lý để khẳng định iterator. (ví dụ như một đồ gia dụng thị rất có thể để mắt theo hướng rộng với theo hướng sâu.)

Với đối tượng người sử dụng iterator, nó rất cần phải được cài đặt nhì cách thức sau, với cỗ nhì cách tiến hành này được Hotline là giao thức iteration.

Phương thức __iter__ trả về chính đối tượng người sử dụng iterator. Phương thơm thức này được yên cầu thiết đặt cho cả đối tượng "iterable" cùng iterator để rất có thể sử dụng các câu lệnh for cùng in.Phương thơm thức __next__ (sinh hoạt Pykhông lớn 2 là next) trả về thành phần tiếp theo sau. Nếu không còn thành phần như thế nào nữa thì StopIteration exception sẽ được raise.

Một hàm dựng sẵn của Pybé là iter dìm nguồn vào là một trong đối tượng người dùng "iterable" với trả về tác dụng là một trong những iterator.

Chúng ta hoàn toàn có thể tự setup iterator là một trong class. lấy ví dụ bên dưới đây là một iterator hoạt động tương tự như nlỗi 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 Phương thức __iter__ đã làm cho đối tượng phát triển thành đối tượng người dùng "iterable". Về bản chất, hàm iter sẽ call mang đến thủ tục __iter__ này của từng đối tượng.

Giá trị trả về của __iter__ là một trong iterator. Nó cần phải có cách làm __next__ với cần trả về StopIteration trường hợp không còn phần demo làm sao 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 make them so return self def __next__(self): if self.i Iterator của Pybé có một Điểm sáng là nó chỉ hoàn toàn có thể được chuyên chú qua 1 lần. Nên nếu như đã chăm bẵm qua thành phần làm sao rồi thì các bạn tất yêu trông nom qua nó thêm lần làm sao nữa.

Vì điểm lưu ý bên trên, bắt buộc ví như iterator với đối tượng người dùng "iterable" là 1 trong những, thì nó cũng chỉ hoàn toàn có thể tiến hành iteration một lần. Nhưng giả dụ chúng chưa hẳn là 1 trong, thì bạn cũng có thể tiến hành bao nhiêu lần tùy ý.

def yrange(n): i = 0 while i Mỗi lần lệnh yield được chạy, nó vẫn ra đời một quý giá bắt đầu. (Vì nuốm nó mới được hotline là generator)

Từ generator được sử dụng cho cả hàm (hàm generator là hàm vẫn nói làm việc trên) với kết quả nhưng hàm đó hình thành (đối tượng người tiêu dùng được hàm generator có mặt cũng khá được hotline là generator). Vì vậy đôi khi vấn đề này khiến khó khăn đọc một ít.

Vậy một generator hoạt động như thế nào? khi hàm generator được Call, nó trả công dụng là 1 đối tượng người sử dụng generator với ko đích thực hotline cùng xúc tiến hàm. khi cách tiến hành __next__ được Điện thoại tư vấn, hàm generator vẫn bước đầu chạy, cho tới khi nó gặp lệnh yield. Giá trị được yield sẽ tiến hành trả về đến hàm __next__.

ví dụ như tiếp sau đây minch họa quá trình can hệ thân yield và __next__ trong một đối tượng người tiêu 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 vươn lên là thể của danh mục comprehension. Nó trông siêu giống danh mục comprehension nhưng nó trả về một generator thay vị một menu.

Đơn giản hóa code

Đơn giản hóa code là một tác dụng của hàm với biểu thức generator. Để minch họa mang đến việc này, họ sẽ đem một ví dụ rõ ràng.

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

Đầu tiên, một giải pháp làm thường thì sẽ là áp dụng 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 bên trên dễ dàng với dễ hiểu. Tất nhiên là nó hoạt động tốt, không tính một vấn đề nhỏ là nó lưu giữ toàn bộ các mục vào bộ lưu trữ. Trong đa số những ngôi trường hợp, điều này là ko giỏi Khi phải sử dụng mang lại dung lượng bộ nhớ lưu trữ bự mang lại vậy.

Xem thêm: Cách Ướp Thịt Nướng Lụi Ngon Không Bị Khô Ng Bị Khô Ngon Khó Cưỡng

Bây giờ, chúng ta test áp dụng iterator. Dưới đấy là một thiết lập mang lại Việc 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 bên trên sẽ chuyển động như chúng ta mong muốn, dẫu vậy nó tất cả một trong những vấn đề như:

Có những mẫu mã dựng sẵn được sử dụngLogic được mô tả một biện pháp phức tạpCode bắt đầu quá lâu năm chỉ để tạo ra một iterator

Chúng ta hoàn toàn có thể sử dụng generator để sản xuất iterator nlắp gọn hơn. Chúng ta rất 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à 1 trong những ví dụ minh họa. Pybé tất cả hàm dựng sẵn là range vận động giống như những điều đó. Tất nhiên là thực tế 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 hoàn toàn có thể nâng cấp năng suất bởi vì generator chỉ thực sự sinh hiệu quả Lúc được hotline. Do kia, nó vẫn thực hiện ít bộ nhớ lưu trữ rộng. Hình như, chúng ta không cần phải ngóng tất cả các phần tử của nó được ra đời hết new rất có thể thực hiện. Chúng sẽ được sinc trong quy trình họ hotline generator. Đây là các hiệu quả giành được khi họ sử dụng iterator, mà generator là giải pháp nlắp gọn để tạo thành một iterator.

Để minh họa, bọn họ đã đối chiếu nhì hàm dựng sẵn của Pyeo hẹp 2 là range và xrange.

Cả range với xrange đông đảo biểu hiện một khoảng tầm những số nguim. Tuy nhiên, range trả về một các mục còn xrange trả về một generator.

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

# using non-generatorsum_of_first_n = sum(range(1000000))# using generatorsum_of_first_n = sum(xrange(1000000))Hai mẫu code trông khá giống nhau. Tuy nhiên việc thực hiện range tốn bộ nhớ lưu trữ cùng thời hạn hơn.

Lúc họ áp dụng range, nó sẽ xây dựng danh mục 1 triệu thành phần và sau đó tính tổng của bọn chúng. Việc này khôn xiết tiêu tốn lãng phí bộ lưu trữ vì chưng họ chỉ việc tính tổng của chúng nhưng mà thôi. Sự lãng phí càng tăng thêm khi con số phần tử tăng thêm cùng form size từng thành phần cũng lớn hơn.

Vì rất nhiều công dụng của generator mà vào Pybé nhỏ 3, hàm range hoạt động giống với xrange của Pythuôn 2, Tức là nó đã trả về generator chứ chưa hẳn là menu.

Lưu ý Điểm sáng của iterator là nó chỉ coi ngó qua một lần, nên việc áp dụng generator đã đem đến tác dụng trường hợp bọn họ không mong muốn để mắt nó nhiều hơn nữa 1 lần.

Hãy để mắt tới ví dụ sau:

a = sum(xrange(1000000))p = product(xrange(1000000))Giả sử rằng câu hỏi sinh một số trong những khôn xiết tốn thời hạn cùng bộ nhớ, thì vào ví dụ bên trên, họ đang tiến hành các bước tốn kỉm này gấp đôi. Trong ngôi trường thích hợp này, bài toán thực hiện menu và giữ sẵn trong bộ nhớ dường như hiệu quả hơn.

nums = list(xrange(1000000))a = sum(nums)p = product(nums)Vì vậy Việc gạn lọc sử dụng generator hay là không nhờ vào các vào thực tế đòi hỏi của quá trình. Nên các bạn hãy cân nhắc với tuyển lựa cảnh giác.

Itertools

Module itertools là thỏng viện chuẩn chỉnh của Pyeo hẹp. Nó cung ứng mang lại họ không ít chính sách để làm vấn đề với những iterator.

Trong nội dung bài viết này, họ đang điểm qua một số hàm độc đáo.

chain vẫn gộp những iterator cùng nhau tạo thành một iterator.