__reversed__魔法

时间:2016-08-02 15:55:33

标签: python magic-methods

我有类Count,它有3个参数,包括self,mystart和myend。它应该使用魔术方法__iter____next____reversed__计算从mystart到myend(也是反转)。我已经实现了所有三种魔术方法。但我仍然不确定它是否是实施下一步和反向方法的正确方法。是否有可能我可以在我的__next____reversed__方法中调用内置函数并进行反转,还是有任何pythonic方式?

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))

2 个答案:

答案 0 :(得分: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 :(得分:1)

你正在混淆Iterators和Iterables:

迭代器:

  1. 保持与当前迭代进度相关联的状态
  2. 实施__next__以获得下一个州
  3. 实施__iter__返回。
  4. Iterables:

    1. 包含(或使用某些规则定义)可以遍历的元素集合
    2. 实现__iter__以返回可遍历元素的迭代器
    3. 可以实现__reversed__以返回倒退的迭代器。
    4. The __reversed__ magic method is:

        

      通过reverse()内置调用(如果存在)来实现反向   迭代。它应该返回迭代的一个新的迭代器对象   容器中的所有对象的顺序相反。

      所以你可能不希望实现迭代中可以__reversed__迭代的迭代器,例如实现in your answer意味着这段代码:

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

      会导致无限循环,输出只是重复这种模式:

      1 4
      1 3
      1 2
      1 1
      

      原因是因为两个for循环在相反的方向上正在改变self.current,外部循环将它递增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)