Python大殺器--迭代器、生成器

要判斷一個Pythonista編寫的代碼夠不夠pythonic,一個很重要的標準就是看他能不能靈活運用迭代器。
首先要介紹一下什麼是迭代器:在python中有兩種循環語句,while和for。通常我們可以以c風格來使用它們,但是python額外提供了另外一種更爲方便和高效的使用方式。通俗的來說就是邊生產邊消費。代碼易讀性和簡潔高效性之爭
首先要介紹一下幾個概念之間得差異:

  1. 可迭代對象: 除了列表、元組、字符串、元組、集合、字典等序列外,只要實現了__iter__和__getitem__中任意一個方法的對象都是可以進行迭代的。不同的是,在進行迭代的時候解釋器會調用iter函數,iter函數會檢查對象是否實現了__iter__方法,如果實現了就會調用它得到一個生成器,如果沒有實現__iter__方法但是實現了 __getitem__方法,Python 會創建一個迭代器, 嘗試按順序(從索引 0 開始) 獲取元素。isinstance(objiect, Iterable)只會檢測__iter__方法,忽略了__getitem__方法。

    # coding=utf8
    from collections import Iterable
    
    list_a = [3, 3, 45, 6]
    dict_b = {'a': 'ji', 'b': 'ok', 'c': 'illegall'}
    set_c = {'df', 'fdk', 'lo'}
    tuple_d = ('jfk', 'dj', 'ilsl')
    str_e = 'jkilljls'
    isinstance(list_a, Iterable)  # True 列表是可迭代對象
    isinstance(dict_b, Iterable)  # True 字典是可迭代對象
    isinstance(set_c, Iterable)  # True 集合是可迭代對象
    isinstance(tuple_d, Iterable)  # True 元組是可迭代對象
    isinstance(str_e, Iterable)  # True 字符串是可迭代對象
    

    在這裏插入圖片描述

    class Queue:
    	def __init__(self, q):
        	self.queue = q
    
    	def __iter__(self):
        	for item in self.queue:
            	yield item
    
    	# def __getitem__(self, item):
    	#     return self.queue[item]
    
    queue = Queue([1, 4, 5, 8])
    print(isinstance(queue, Iterable))  #True 只要實現了__iter__方法則該對象就是可迭代對象,還有其他情況見後面
    
    class Queue:
    	def __init__(self, q):
        	self.queue = q
    
    	#def __iter__(self):
    	#    for item in self.queue:
     	#        yield item
    
    	def __getitem__(self, item):
      		return self.queue[item]
    
    queue = Queue([1, 4, 5, 8])
    isinstance(queue, Iterable)  #False 沒有實現__iter__方法,但是實現了__getitem__方法也是可迭代對象
    							 #Iterable只對__iter__方法進行檢測
    for item in queue:  # 只要實現了__iter__和__getitem__中的任意一個,則該對象都是可以進行迭代的。
    	print(item)   
    
  2. 迭代器: 實現了next方法和__iter__方法的對象,且next方法實現了迭代協議,__iter__方法返回迭代器。
    如下是一個迭代器類,可以產生迭代器對象,對迭代器對象調用iter函數返回迭代器類自身,迭代環境中自動調用__next__方法。

    class iter:
    	def __init__(self, data):
    		self.data = data
    		self.now = 0
    	
    	def __iter__(self):
    		return self
    	
    	def __next__(self):
    		if self.now < data:
    			self.now += 1
    			return (self.now-1)**2
    		 raise StopIteration 
    
  3. 生成器:生成器是一種特殊的迭代器,生成器自動實現了“迭代器協議”(即__iter__和next方法),不需要再手動實現兩方法。
    3.1 生成器表達式:可以使用表達式來得到生成器
    使用生成器表達式可以非常輕鬆的得到生成器,只要將列表解析式中的方括號換成圓括號就可以了。

    (x for x in range(5))  # iterator
    

    3.2 生成器函數:在函數中使用關鍵詞yield得到生成器

    def gen(num):
    	cou = 0
    	while cou < num:
    		yield cou
    		cou += 1
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章