计算范围内的平方数(python)

时间:2015-05-15 08:12:31

标签: python iterator

我希望能够执行以下代码:

for i in Squares(5, 50):
      print(i)

现在使用循环很容易实现,但是我想使用迭代器。

所以我定义了以下类:

import math

class Squares(object):

    def __init__(self, start, stop):
       self.start = start
       self.stop = stop

    def __iter__(self): 
        return self

    def __next__(self):
        start = self.start
        stop = self.stop
        squareroot = math.sqrt(start)

        if self.start > self.stop:
            raise StopIteration

        if squareroot == math.ceil(squareroot):
            start += 1

但目前这已经无数次返回None。这意味着必须是因为StopIteration正在被执行,即使它不应该被执行。我认为我的if squareroot == math.ceil(squareroot):条件是正确的,因为我单独测试了它,但是我无法弄清楚要改变什么来获得我想要的输出。任何帮助表示赞赏。

编辑:对于代码如:

for i in Squares(4, 16):
    print(i)

我希望输出为:

4
9
16

6 个答案:

答案 0 :(得分:3)

尝试创建生成器函数:

from math import sqrt, ceil

def Squares(start, stop):
    for i in range(start, stop+1):
        sqrti = sqrt(i)
        if sqrti == ceil(sqrti):
            yield i

然后循环它:

for i in Squares(4, 20):
    print i,

提示:

4 9 16

编辑:编辑以匹配方形定义,而不是之前的平方功率(抱歉:P)。在范围中添加+1以匹配OP的问题示例。

答案 1 :(得分:2)

我认为你的意思是继续递增直到它到达下一个方格,而不是仅当它是一个正方形时才增加它:

def __next__(self):
    self.start += 1
    squareroot = math.sqrt(self.start)
    while squareroot != math.ceil(squareroot):
        if self.start > self.stop:
            raise StopIteration
        self.start += 1
        squareroot = math.sqrt(self.start)

答案 2 :(得分:2)

您可以简单地做到这一点

def squares(start, end): 
return [i**2 for i in range(start, end+1) ]

所以结果

print(squares(1, 5))

将是:

[1、4、9、16、25]

答案 3 :(得分:1)

您可以使用

简化算术
(n + 1)**2 == n**2 + (2*n + 1)

以下是使用生成器函数的方法:

import math

def squares(lo, hi):
    root = int(math.ceil(lo ** 0.5))
    num = root ** 2
    delta = 2 * root + 1
    while num <= hi:
        yield num
        num += delta
        delta += 2

print list(squares(4, 16))
print list(squares(5, 50))
print list(squares(20, 90))

<强>输出

[4, 9, 16]
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]

这是一个等效的迭代器类。我已经给它一个__repr__方法,所以如果你打印这个类的实例它看起来不错。

import math

class Squares(object):
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop
        root = int(math.ceil(start ** 0.5))
        self.num = root ** 2
        self.delta = 2 * root + 1

    def __repr__(self):
        return 'Squares(%d, %d)' % (self.start, self.stop)

    def __iter__(self): 
        return self

    def next(self):
        num = self.num
        if num > self.stop:
            raise StopIteration
        self.num += self.delta
        self.delta += 2
        return num

sq = Squares(4, 16)
print sq
for i in sq:
    print i

print list(Squares(5, 50))
print list(Squares(20, 90))

<强>输出

Squares(4, 16)
4
9
16
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]

对于Python 3,将next方法名称替换为__next__

通常的Python range约定是在达到上限之前停止。要使此代码符合该约定,请在squares()生成器更改

while num <= hi:

while num < hi:

并在Squares()课程中,更改

if num > self.stop:

if num >= self.stop:

答案 4 :(得分:0)

最简单的是:


import math


class Squares(object):

    def __init__(self, start, stop):
        self._squares = range(start, stop + 1)

    def __iter__(self):
        return self._squares.__iter__()

    def __next__(self):
        if math.sqrt(self._squares.next()) == math.ceil(math.sqrt(self._squares.next())): 
            return math.sqrt(self._squares.next()) 


if __name__ == '__main__':
    for i in Squares(5, 50):
        print i

答案 5 :(得分:0)

from math import ceil, sqrt
start,stop = 4,16
gen_sqr = (  i for i in range( start, stop +1) if sqrt(i) == ceil( sqrt(i)) ) 

现在你有了自己的方块生成器:

gen_sqr.next() #4
gen_sqr.next() #9
list(gen_sqr) #[16]