環境
- 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
はクラス変数として宣言しているので、問題ないようにみえます。
原因と解決策
Cat
とBird
でコンストラクタ引数が合っていないから、エラーが出ているようです。
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