0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

@dataclassとEnum使ってたらはまった話

Posted at

普段、pythonでコードを書いているのですが、先日@dataclassとEnumの組み合わせではまったので備忘録として記載します。
pythonについては既存のコードを見つついじる程度の知識しかないので、そもそもこんな風につかわないよ!等あるかもしれません。
既存コードを参考に書いていましたが、Enumに@dataclassつける意味あるのか?と最近ではうっすら思っていますが、事象として興味深かったのでまとめました。

どうはまったのか

以下のようなEnumを定義しました。

@dataclass
class Fruits(Enum):
    APPLE = 0
    BANANA = 1
    CHERRY = 2

処理の都合上、APPLEとBANANAのみ処理をしたかったので、以下のようなコードを描きました。

if fruit in [Fruits.APPLE, Fruits.BANANA]:
    # リンゴかバナナであれば処理をする

fruit=Fruits.CHERRYを代入し、実行したところ、処理が行われてしまいました。
この辺りを整理してみたところ、以下のような結果となりました。

結果
Fruits.CHERRY in Fruits True
Fruits.APPLE in [Fruits.APPLE, Fruits.BANANA] True
Fruits.CHERRY in [Fruits.APPLE, Fruits.BANANA] True Falseを想定したのにTrueになっていた
Fruits.CHERRY is Fruits.APPLE or Fruits.CHERRY is Fruits.BANANA False

dataclassを付けない場合

一方で、以前に同様のコードを書いたときは動いていた記憶があったので、確認してみるとそのコードには@dataclassがついていませんでした。

class Vegetables(Enum):
    AVOCADO = 0
    BROCCOLI = 1
    CARROT = 2

こちらは以下のような結果となりました。

結果
Vegetables.AVOCADO in Vegetables True
Vegetables.AVOCADO in [Vegetables.AVOCADO, Vegetables.BROCCOLI] True
Vegetables.CARROT in [Vegetables.AVOCADO, Vegetables.BROCCOLI] False 想定通り
Vegetables.CARROT is Vegetables.AVOCADO or Vegetables.CARROT is Vegetables.BROCCOLI False

なぜ?

問題の起こった評価式をログで出力してみたところ、以下のようになりました。

結果
[Fruits.APPLE, Fruits.BANANA] [Fruits(), Fruits()]
[Vegetables.AVOCADO, Vegetables.BROCCOLI] [<Vegetables.AVOCADO: 0>, <Vegetables.BROCCOLI: 1>]

@dataclassがついていない場合(Vegetables)はそれぞれの要素になっているのに対して、@dataclassがついている場合(Fruits)はオブジェクトになっている?ようです。(ちょっとこへんよくわかっていないです)
これによってfruit in [Fruits.APPLE, Fruits.BANANA]はfruitにCHERRYが入っていても、Fruitsの要素だったらオッケー!といった評価になったようです。

最後に

この事象はユニットテストが通らなかったことで発見したので、ユニットテストは本当に大事だなと思います。
既存コードにあるからといって、何となくコピーで使うのは良くないなと改めて思いました。

やっぱり、Enumに@dataclassついてるのおかしくない?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?