2015-05-15 32 views
5

我希望能夠執行以下代碼:計算一個範圍(蟒蛇)內的平方數

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 
+0

什麼是O/P你期待? (3,4,5,6,7)? –

+0

當'start'是一個正方形時,你只會遞增'start'。這意味着它會陷入第一個非正方形。 – Kittsil

+0

@ Bhargav Rao我剛剛編輯:) – ASm

回答

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的問題示例。

+0

這是一個發電機:d – CristiFati

+0

@CristiFati True,thx! :P –

+0

這並不回答如何使用迭代器找到範圍內的所有方塊的問題......這是一個非常好的答案,但涉及到另一個問題。 – Kittsil

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

+0

難道這只是打印從5到49的所有數字嗎? – ASm

+0

對,我衝了一下,修正了 –

+0

現在它打印所有從sqrt(5)到sqrt(50)的平方根... – Kittsil

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: 
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]