developerWorks の記事にある Python コードを修正してみた

IBM が運営している技術サイト developerWorks には Python の記事がちょくちょく載っているんだけど、Python コードのインデントが崩れていて大変悲しい (最初は日本語版だけかなと思ったら、もとの原文からしてインデントが崩れまくってた)。
そこで、勝手ながら崩れたインデントを修復してみた。今回のターゲットは次の記事。


元記事のインデントがどのくらい崩れているかというと、こんな感じ。ひどいでしょ?

ところで、この記事は2000年に書かれており、Python コードとしては古い書き方をしていた。そこでインデントを修復するだけでなく、より新しい書き方に変更してみた。具体的には、以下のような変更を行っている。

  • 1/0 ではなく True/False を使う
  • 親クラスを省略せずに object を指定する
  • raise の引数を文字列ではなく Exception オブジェクトにする
  • string モジュールを使わず、かわりに文字列メソッドを使う


それではインデント修復版をどうぞ。

# -*- coding: utf-8 -*-
## from http://www.ibm.com/developerworks/jp/linux/library/l-python-state/#N101C3
## ファイル名: statemachine.py

class StateMachine(object):

    def __init__(self):
        self.handlers = {}
        self.startState = None
        self.endStates = []

    def add_state(self, name, handler, end_state=False):
        name = name.upper()
        self.handlers[name] = handler
        if end_state:
            self.endStates.append(name)

    def set_start(self, name):
        self.startState = name.upper()

    def run(self, cargo):
        try:
            handler = self.handlers[self.startState]
        except:
            raise Exception("must call .set_start() before .run()")
        if not self.endStates:
            raise Exception("at least one state must be an end_state")
        while True:
            newState, cargo = handler(cargo)
            if newState.upper() in self.endStates:
                break
            else:
                handler = self.handlers[newState.upper()]

#ここで「cargo」というのは「積み荷」という意味。
#現在の状態から次の状態へ渡す値のことを指している。

もうひとつ。

# -*- coding: utf-8 -*-
## http://www.ibm.com/developerworks/jp/linux/library/l-python-state/#N1026A
## ファイル名: statemachine_test.py

from statemachine import StateMachine

def ones_counter(val):
    print "ONES State:    ",
    while True:
        if val <= 0 or val >= 30:
            newState = "Out_of_Range" ; break
        elif 20 <= val < 30:
            newState = "TWENTIES"; break
        elif 10 <= val < 20:
            newState = "TENS"; break
        else:
            print " @%2.1f+" % val,
            val = math_func(val)
    print " >>"
    return (newState, val)

def tens_counter(val):
    print "TENS State:    ",
    while True:
        if val <= 0 or val >= 30:
            newState = "Out_of_Range"; break
        elif 1 <= val < 10:
            newState = "ONES"; break
        elif 20 <= val < 30:
            newState = "TWENTIES"; break
        else:
            print " #%2.1f+" % val,
            val = math_func(val)
    print " >>"
    return (newState, val)

def twenties_counter(val):
    print "TWENTIES State:",
    while True:
        if val <= 0 or val >= 30:
            newState = "Out_of_Range"; break
        elif 1 <= val < 10:
            newState = "ONES"; break
        elif 10 <= val < 20:
            newState = "TENS"; break
        else:
            print " *%2.1f+" % val,
            val = math_func(val)
    print " >>"
    return (newState, val)

def math_func(n):
    from math import sin
    return abs(sin(n))*31

if __name__== "__main__":
    m = StateMachine()
    m.add_state("ONES", ones_counter)
    m.add_state("TENS", tens_counter)
    m.add_state("TWENTIES", twenties_counter)
    m.add_state("OUT_OF_RANGE", None, end_state=True)
    m.set_start("ONES")
    m.run(1)


しかしこのコード、あんまりうまくないよな。こんなレベルのコードを掲載するのは developerWorks としてはどうなの?