2016-08-02 53 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)