28

Python 3.6 と mypy で入力する実験を行っています。次の 2 つの方法でインスタンス化できるエンティティ クラスを設計したいと考えています。

  • 通常のイニシャライザを使用する ( p = Person(name='Hannes', age=27))
  • 状態オブジェクト ( ) から静的にp = Person.from_state(person_state)

派生元のEntityクラスには、汎用パラメーターとして状態クラスがあります。Personただし、mypy でコードを検証すると、Person.from_state継承元のクラスから状態の型を取得しないというエラーが表示されます。

untitled2.py:47: エラー: "Entity" の "from_state" への引数 1 に互換性のない型 "UserState" があります。期待される「StateType」

から継承することでEntity[UserState]StateTypeにバインドさUserStateれ、子クラスのメソッド シグネチャがそれに応じて更新されると考えました。

これは完全なコードです。で間違ったことをしていると思われる行に印を付けました?????。行 47 はほぼ最下部にあり、コードでマークされています。

from typing import TypeVar, Generic, NamedTuple, List, NewType

EntityId = NewType('EntityId', str)

StateType = TypeVar('StateType')

class Entity(Generic[StateType]):
    id: EntityId = None
    state: StateType = None

    @classmethod
    def from_state(cls, state: StateType): # ?????
        ret = object.__new__(cls)
        ret.id = None
        ret.state = state
        return ret

    def assign_id(self, id: EntityId) -> None:
        self.id = id

class UserState(NamedTuple):
    name: str
    age: int

class User(Entity[UserState]):
    def __init__(self, name, age) -> None:
        super().__init__()
        self.state = UserState(name=name, age=age)

    @property
    def name(self) -> str:
        return self.state.name

    @property
    def age(self) -> int:
        return self.state.age

    def have_birthday(self) -> None:
        new_age = self.state.age+1
        self.state = self.state._replace(age=new_age)

# Create first object with constructor
u1 = User(name='Anders', age=47)

# Create second object from state
user_state = UserState(name='Hannes', age=27)
u2 = User.from_state(user_state) # Line 47

print(u1.state)
print(u2.state)
4

2 に答える 2