2016-08-02 54 views
0

我有類Count,需要3個參數,包括self,mystart和myend。它應該從mystart開始計算,直到使用神奇的方法__iter__,__next____reversed__我的終點(也是相反的)。我已經實施了所有三種魔術方法。但我仍然不確定這是否是實施下一個逆向方法的正確方法。是否有可能我可以調用內置函數,並在我的__next____reversed__方法中反轉,或者有任何pythonic方法嗎?__reversed__神奇的方法

class Count: 

    def __init__(self,mystart,myend): 
     self.mystart=mystart 
     self.myend=myend 
     self.current=mystart 
     self.reverse=[] 


    def __iter__(self): 
     "Returns itself as an Iterator Object" 
     return self 

    def __next__(self): 
     if self.current > self.myend: 
      raise StopIteration 
     else: 
      self.current+=1 
      return self.current-1 

    def __reversed__(self): 
     for i in range(self.myend,self.mystart,-1): 
      self.reverse.append(i) 
     return self.reverse 


obj1=Count(0,10) 
print("FOR LOOP") 
for i in obj1: 
    print (i,end=",") 

print ("\nNEXT") 
obj2=Count(1,4) 
print(next(obj2)) 
print(next(obj2)) 

print ("Reversed") 
print(reversed(obj1)) 
+0

爲了讓大家知道「正確」的方式是什麼,什麼是期望的結果。你的代碼看起來不是那麼糟糕 – wheaties

+0

但是我在__reversed__方法中創建了一個新列表,這並不給我很好的感覺。 :) –

+1

給迭代器一個'__reversed__'方法沒什麼意義。這是針對具有排序概念的序列和其他多重迭代迭代。 – user2357112

回答

1

現在我已經使用yield語句完成了它。 @jedwards感謝您的tipp。

class Count: 

    def __init__(self, mystart,myend): 
     self.mystart = mystart 
     self.myend = myend 
     self.current=None 

    def __iter__(self): 
     self.current = self.mystart 
     while self.current < self.myend: 
      yield self.current 
      self.current += 1 

    def __next__(self): 
     if self.current is None: 
      self.current=self.mystart     
     if self.current > self.myend: 
      raise StopIteration 
     else: 
      self.current+=1 
      return self.current-1 

    def __reversed__(self): 
     self.current = self.myend 
     while self.current >= self.mystart: 
      yield self.current 
      self.current -= 1 

obj1=Count(0,10)  
for i in obj1: 
    print (i) 

obj2=reversed(obj1) 
for i in obj2: 
    print (i) 

obj3=Count(0,10) 
print (next(obj3)) 
print (next(obj3)) 
print (next(obj3)) 
+1

注意:你的'__next__'方法是無用的,因爲當迭代python會調用'__next__' *生成器*返回'__iter__'(添加一個'print'並檢查它是否從未被調用過)。這個''current''現在只是'__iter__'和'__reversed__'的一個局部變量*,所以你應該真的只需要使用'current'來代替'self.current'並且從'__init__中移除'self.current = None' '。 – Bakuriu

+0

是的,你是對的。 –

1

你混合了迭代器和Iterables:

迭代:

  1. 保持與他們的當前迭代的進展
  2. 相關的國家實行__next__獲得下一個狀態
  3. 實施__iter__返回自己。

Iterables:

  1. 含(或與一些規則定義)的元素的集合,該集合可以被穿越
  2. 實施__iter__返回可遍歷元件進行迭代的迭代
  3. 可以實現__reversed__返回一個反向的迭代器。

The __reversed__ magic method is:

調用(如果存在)通過反轉()內置實現扭轉 迭代。它應該返回一個新的迭代器對象,它以相反的順序遍歷容器中的所有對象。

所以,你可能不希望實現一個迭代器,可以__reversed__中旬迭代,例如實施in your answer意味着這個代碼:

x = Count(1,10) 
for i in x: 
    for j in x: 
     print(i,j) 

會導致無限循環,輸出只是這種模式重複:

這樣做的原因是,因爲兩個for環在相反的方向變更self.current s,外部循環會將其增加1,然後內部循環將其設置爲self.myend並將其降低迴0,然後重複該過程。

正確實現所有三個魔術方法的唯一方法是使用兩個班,一個是迭代器和一個用於迭代:

class _Count_iter: 
    def __init__(self, start, stop, step=1): 
     self.current = start 
     self.step = step 
     self.myend = stop 

    def __iter__(self):return self 

    def __next__(self): 
     #if current is one step over the end 
     if self.current == self.myend+self.step: 
      raise StopIteration 
     else: 
      self.current+=self.step 
      return self.current-self.step 


class Count: 

    def __init__(self, mystart,myend): 
     self.mystart = mystart 
     self.myend = myend 

    def __iter__(self): 
     return _Count_iter(self.mystart,self.myend,1) 
    def __reversed__(self): 
     return _Count_iter(self.myend, self.mystart, -1)