如何修改Python操作符?

2024-05-12 19:03:32 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我的Fib-squence的迭代器:

class fibo:

  def __init__(self, n=0):
     self.n = n
     self.x1 = 0
     self.x2 = 1

  def next(self):
      if self.n == 0:
          raise StopIteration
      else:
          self.n = self.n -1
          tmp = self.x1
          self.x1, self.x2 = self.x2, self.x1 + self.x2
          return tmp

  def __iter__(self):
      return self

结果是

^{pr2}$

如何修改代码,使连续调用迭代下一个n个Fibonacci数,而不是迭代前n个Fibonacci数,例如????在

>>> f=fibo(5)

>>> [i for i in f]
[0, 1, 1, 2, 3]

>>> [i for i in f]
[5, 8, 13, 21, 34]
>>> [i for i in f]
[55, 89, 144, 233, 377]
>>> [i for i in f]
[610, 987, 1597, 2584, 4181]

Tags: inselfforreturninitdeftmpclass
3条回答

为了得到您想要的东西,但是语法不同,您可以使用What is the most “pythonic” way to iterate over a list in chunks?的答案。尤其是来自one of the answers的代码片段:

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return izip_longest(*args, fillvalue=fillvalue)

这个函数将把iterable分成大小相等的“块”。您可以将其与现有的fibo类的非终止版本一起使用:

^{pr2}$

组合起来,现在可以执行以下操作:

^{3}$

请注意,这个修改过的fibo永远不会停止迭代,所以您需要小心地将它交给任何试图急切地迭代到最后的东西。在

另外,下面是一个使用生成器而不是类的迭代器的替代实现:

def fibg():
    x1 = 0
    x2 = 1
    while True:
        yield x1
        x1, x2 = x2, x1 + x2

这在2.7中有效

class fibo:

    def __init__(self, n=0):
        self.n = n
        self.x1 = 0
        self.x2 = 1
        self.current = 0 #We won't decrease n, but instead increase current until it
                             #Equals n

    def next(self):
        if self.n == self.current:
            self.current = 0
            raise StopIteration
        else:
            self.current +=1
            tmp = self.x1
            self.x1, self.x2 = self.x2, self.x1 + self.x2
            return tmp

    def __iter__(self):
        return self

f = fibo(5)
print [i for i in f]
print [i for i in f]

输出

^{pr2}$

在Python中,获取所需的确切语法是完全非法的,或者是非常不鼓励的,因为迭代器协议要求迭代器在完成一次之后继续生成StopIteration。来自引入迭代器的PEP 234

  - Once a particular iterator object has raised StopIteration, will
  it also raise StopIteration on all subsequent next() calls?
  Some say that it would be useful to require this, others say
  that it is useful to leave this open to individual iterators.
  Note that this may require an additional state bit for some
  iterator implementations (e.g. function-wrapping iterators).

  Resolution: once StopIteration is raised, calling it.next()
  continues to raise StopIteration.

EDIT再想一想,我认为您需要的实际上是“合法的”Python,因为list comprehension [i for i in fibo]隐式调用fibo上的__iter__方法,因此或多或少要求一个新的迭代器(即使这是由同一个对象实现的)。因此,实现您想要的行为的正确方法是:

^{pr2}$

工作原理如下:

^{3}$

这显示了所需的行为:它继续引发StopIteration当它耗尽时,您需要显式地调用iter来重置它。这与C.B.的版本稍有不同,C.B.的版本只是简单地包装起来,不需要重置:

In [45]: f = fibo(3)
In [46]: it = iter(f)
In [47]: it.next()
Out[47]: 0
In [48]: it.next()
Out[48]: 1
In [49]: it.next()
Out[49]: 1
In [50]: it.next()
-> StopIteration
In [51]: it.next() # no need to reset!
Out[51]: 2
In [52]: it.next()
Out[52]: 3
In [53]: it.next()
Out[53]: 5
In [54]: it.next()
-> StopIteration

相关问题 更多 >