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?

More than 1 year has passed since last update.

データクラスとデータクラスでないクラスのクラス変数をまとめて参照すると、mypyでエラーが発生した

Last updated at Posted at 2023-05-03

環境

  • Python 3.11.2
  • mypy 1.2.0

やりたいこと

dataclassのCatと、通常のクラスBirdのクラス変数animal_nameを出力したいです。

sample.py
from dataclasses import dataclass
from typing import ClassVar


class Animal:
    animal_name: ClassVar[str]


@dataclass
class Cat(Animal):
    cat_id: str
    animal_name: ClassVar[str] = "cat"

    def only_cat_method(self) -> None:
        print("only cat method")


class Bird(Animal):
    """Not dataclass"""

    animal_name: ClassVar[str] = "bird"

    def only_bird_method(self) -> None:
        print("only bird method")


for cls in [Cat, Bird]:
    print(cls.animal_name)
$ python sample.py 
cat
bird

起きたこと

上記のコードをmypyでチェックすると、エラーが発生しました。

$ mypy sample.py
sample.py:28: error: "type" has no attribute "animal_name"  [attr-defined]
Found 1 error in 1 file (checked 1 source file)

親クラスにもAnimalにもanimal_nameはクラス変数として宣言しているので、問題ないようにみえます。

原因と解決策

CatBirdでコンストラクタ引数が合っていないから、エラーが出ているようです。

Birdに引数が1個の__init__メソッドを宣言したら、mypyでエラーは出なくなりました。

class Bird(Animal):
    """Not dataclass"""
    animal_name: ClassVar[str] = "bird"

    def only_bird_method(self) -> None:
        print("only bird method")

    def __init__(self, foo) -> None:
        pass

mypyのドキュメントに記載されている通り、特殊メソッドもチェックしているようです。

Mypy will detect special methods (such as lt) depending on the flags used to define dataclasses. 1

ただし、エラーメッセージが正しくない気がします。2

  1. https://mypy.readthedocs.io/en/stable/additional_features.html#dataclasses

  2. issueで報告しました。

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?