Engineer as a Lifestyle @tenkoma

What We Find Changes Who We Become -- Peter Morville『アンビエント・ファインダビリティ 』

Re:Pythonのジェネレータで四角いらせんを書いた:西尾泰和のブログ

無理矢理短く書いてみた

def squareSpiralX():
    width = 0
    (x,y) = (0,0)
    yield (0,0)
    phase = ((+1,0),(0,+1),(-1,0),(0,-1))
    while True:
        for p in phase:
            if p[1] == 0:
                width += 1
            for i in range(width):
                x += p[0]
                y += p[1]
                yield (x,y)

書いてみて,いくつかの欠点があることに気がつく

  • ブロックネストの数が増えた
  • if文がある
  • 拡張代入の文(x += p[0],y += p[1])のうちどちらかは無意味になる

もとのコードでif文なしで状態遷移を表現しているところがおもしろいんだな.
実行効率も調べてみる

import profile
>>> gx =squareSpiralX()
>>> profile.run('for i in range(100000):xy = gx.next()')
         100636 function calls in 1.280 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      633    0.000    0.000    0.000    0.000 :0(range)
        1    0.000    0.000    0.000    0.000 :0(setprofile)
   100000    0.570    0.000    0.570    0.000 <pyshell#40>:1(squareSpiralX)
        1    0.710    0.710    1.280    1.280 <string>:1(?)
        1    0.000    0.000    1.280    1.280 profile:0(for i in range(100000):xy = gx.next())
        0    0.000             0.000          profile:0(profiler)


>>> g = squareSpiral()
>>> profile.run('for i in range(100000):xy = g.next()')
         100636 function calls in 1.090 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      633    0.020    0.000    0.020    0.000 :0(range)
        1    0.000    0.000    0.000    0.000 :0(setprofile)
   100000    0.470    0.000    0.490    0.000 <pyshell#33>:1(squareSpiral)
        1    0.600    0.600    1.090    1.090 <string>:1(?)
        1    0.000    0.000    1.090    1.090 profile:0(for i in range(100000):xy = g.next())
        0    0.000             0.000          profile:0(profiler)

2割弱処理時間が増えました.