Skip to content

Instantly share code, notes, and snippets.

@hikaru-y
Created April 7, 2024 18:07
Show Gist options
  • Save hikaru-y/86e067d64ffa09a4d23bb1307ab18212 to your computer and use it in GitHub Desktop.
Save hikaru-y/86e067d64ffa09a4d23bb1307ab18212 to your computer and use it in GitHub Desktop.
FSM
User
pythonで有限状態マシーンを実装しようと思っています。コルーチン(Generator)を使って実装することは可能でしょうか?
ChatGPT
はい、Pythonで有限状態マシンを実装するためにコルーチン(Generator)を使用することは可能です。コルーチンは、状態と状態遷移を効果的に表現し、シンプルな構造で状態遷移を制御するのに役立ちます。以下に、コルーチンを使用して有限状態マシンを実装する基本的な例を示します。
python
Copy code
def state_machine():
state = "start"
while True:
if state == "start":
print("Starting state...")
# ここで何らかの処理を行う
state = yield "started"
elif state == "middle":
print("Middle state...")
# ここで何らかの処理を行う
state = yield "in middle"
elif state == "end":
print("End state...")
# ここで何らかの処理を行う
state = yield "finished"
else:
raise ValueError("Invalid state")
# 有限状態マシンのインスタンスを作成
machine = state_machine()
# 最初の状態に進む
print(next(machine)) # Output: Starting state... started
# 中間の状態に進む
print(machine.send("middle")) # Output: Middle state... in middle
# 最後の状態に進む
print(machine.send("end")) # Output: End state... finished
この例では、state_machine関数内のコードが各状態に対応し、適切な処理を行います。yieldステートメントは、状態の切り替えを行い、次の状態への制御を呼び出し元に返します。sendメソッドを使って、次の状態に進みます。このようにして、コルーチンを使用して状態遷移を簡潔かつ直感的に制御することができます。
User
クラスを使って同じように実装することはできますか?
ChatGPT
はい、クラスを使用しても同じように有限状態マシンを実装することができます。以下に、クラスを使用した有限状態マシンの実装例を示します。
python
Copy code
class StateMachine:
def __init__(self):
self.state = "start"
def start(self):
print("Starting state...")
# ここで何らかの処理を行う
self.state = "middle"
return "started"
def middle(self):
print("Middle state...")
# ここで何らかの処理を行う
self.state = "end"
return "in middle"
def end(self):
print("End state...")
# ここで何らかの処理を行う
self.state = "start" # ここで状態を初期状態にリセットする例
return "finished"
# 有限状態マシンのインスタンスを作成
machine = StateMachine()
# 最初の状態に進む
print(machine.start()) # Output: Starting state... started
# 中間の状態に進む
print(machine.middle()) # Output: Middle state... in middle
# 最後の状態に進む
print(machine.end()) # Output: End state... finished
この例では、StateMachineクラスが各状態に対応するメソッドを持ち、それぞれのメソッド内で適切な処理を行います。各メソッドは次の状態に遷移し、その状態のラベルを返します。状態遷移の制御はクラス内で行われます。
どちらの方法でも、有限状態マシンを柔軟かつ効率的に実装できますが、使用する場面や好みによって選択することができます。
User
クラスとgeneratorを組み合わせて実装したいです
ChatGPT
クラスとジェネレータを組み合わせて、状態マシンを実装することも可能です。ジェネレータを使うことで、状態を保持し、各状態での処理を行うことができます。以下に、クラスとジェネレータを組み合わせた有限状態マシンの実装例を示します。
python
Copy code
class StateMachine:
def __init__(self):
self.state_generator = self.state_machine()
def state_machine(self):
state = "start"
while True:
if state == "start":
print("Starting state...")
# ここで何らかの処理を行う
state = yield "started"
elif state == "middle":
print("Middle state...")
# ここで何らかの処理を行う
state = yield "in middle"
elif state == "end":
print("End state...")
# ここで何らかの処理を行う
state = yield "finished"
else:
raise ValueError("Invalid state")
def start(self):
return next(self.state_generator)
def middle(self):
return self.state_generator.send("middle")
def end(self):
return self.state_generator.send("end")
# 有限状態マシンのインスタンスを作成
machine = StateMachine()
# 最初の状態に進む
print(machine.start()) # Output: Starting state... started
# 中間の状態に進む
print(machine.middle()) # Output: Middle state... in middle
# 最後の状態に進む
print(machine.end()) # Output: End state... finished
この実装では、state_machineメソッド内でジェネレータが状態を保持し、各状態での処理を行います。クラスのメソッド start、middle、end はそれぞれ、ジェネレータに対して next と send を呼び出し、状態の遷移を制御します。
このように、クラスとジェネレータを組み合わせることで、状態マシンを柔軟に実装することができます。
User
endメソッドを呼んだ時にstate_generatorを抜けるようにすることはできますか
ChatGPT
はい、endメソッドを呼んだときにジェネレータから抜けるようにすることができます。これを行うには、ジェネレータに終了条件を追加し、endメソッドを呼び出した際に終了条件を満たすようにジェネレータを操作します。以下はその方法を示したコードです。
python
Copy code
class StateMachine:
def __init__(self):
self.state_generator = self.state_machine()
def state_machine(self):
state = "start"
while True:
if state == "start":
print("Starting state...")
# ここで何らかの処理を行う
state = yield "started"
elif state == "middle":
print("Middle state...")
# ここで何らかの処理を行う
state = yield "in middle"
elif state == "end":
print("End state...")
# ここで何らかの処理を行う
break # ジェネレータを終了
else:
raise ValueError("Invalid state")
def start(self):
return next(self.state_generator)
def middle(self):
return self.state_generator.send("middle")
def end(self):
try:
self.state_generator.send("end")
except StopIteration:
print("State machine finished.")
# 有限状態マシンのインスタンスを作成
machine = StateMachine()
# 最初の状態に進む
print(machine.start()) # Output: Starting state... started
# 中間の状態に進む
print(machine.middle()) # Output: Middle state... in middle
# 最後の状態に進む
machine.end() # Output: End state... State machine finished.
この実装では、endメソッドが呼び出されたときに、state_machineジェネレータ内でbreak文を使用してループを終了させています。そして、endメソッド内でsendを使って"end"をジェネレータに送り、ジェネレータが終了するようにしています。また、endメソッド内でStopIteration例外が発生した場合には、それがジェネレータの終了を示すため、状態マシンが終了したことを示すメッセージを表示しています。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment