🚥
Python の Flag と状態モデルの相性がいい
Python の enum には Flag という機能があることを知りました。入れ子の状態(直和集合にあたるもの)を表現するのに便利そうだと思い使ってみました。
今回はエアコンの状態を例に説明します。
from enum import Flag, IntEnum, auto
class State(Flag):
Off = auto()
Cooling = auto()
Heating = auto()
Dry = auto()
Running = Cooling | Heating | Dry
まず enum 同様以下のように使用できます。
# わかりやすいようにあえて変数名は heat にします
heat = State.Heating
heat
> <State.Heating: 4>
heat == State.Heating
> True
heat == State.Dry
> False
しかし属する親状態への判定が enum だとできません。
heat == State.Running
> False
代替案として以下のように列挙することになります。
heat == State.Heating or heat == State.Dry or heat == State.Cooling
> True
ここで Flag の OR 定義を活かすことができます。
Running = Cooling | Heating | Dry
# 同様
heat in State.Heating
> True
# 同様
heat in State.Dry
> False
# 判定可能!
heat in State.Running
> True
2 重以上の状態に対してももちろん有効です。
class State(Flag):
Off = auto()
Cooling = auto()
HeatingWeak = auto()
HeatingStrong = auto()
Heating = HeatingWeak | HeatingStrong
Dry = auto()
Running = Cooling | Heating | Dry
State.HeatingWeak in State.Running
> True
Rust の enum
enum Heating {Weak, Strong }
enum Running { Cooling, Heating(Heating), Dry }
enum State { Off, Running(Running) }
fn main() {
let state = State::Running(Running::Heating(Heating::Strong));
// match する
// State::Running(Running::Heating(Heating::Strong))
// State::Running(Running::Heating(_))
// State::Running(_)
// match しない
// State::Running(Running::Cooling)
// State::Off
Discussion