This is what I want to do:
class Base:
_type = None
name: str = _type.name
class a(Base):
_type = UnityType
a_instance = a()
a_instance.name # Expecting UnityType.name to be some string.
While trying this, I get 'NoneType' object has no attribute 'name'. The reason is clear and understandable. But how can I pass the responsibility of implementing a variable class to a subclass?
1 Answer 1
I think you need Base.name to be a property, so that it's evaluated when it's accessed rather than when Base is defined:
from typing import Optional, Protocol, Type
class Named(Protocol):
name: str
class Base:
_type: Optional[Type[Named]] = None
@classmethod
@property
def name(cls) -> str:
assert cls._type is not None
return cls._type.name
class UnityType:
name = "Unity"
class a(Base):
_type = UnityType
a_instance = a()
print(a_instance.name) # prints "Unity"
I'm assuming from your example that UnityType is a type, not an instance, and that you want Base to work with either that type or other types with a name class attribute, so I defined a Protocol that requires that and used that for the type annotation of Base (the above passes mypy without complaint).
_typeis astrin the first place if you want it to be something that has anameattribute...__init__()and put the name on the instance when the instance is initialized? Although it's not clear what should happen when someone createsBase().a._type.nameto work ,onlya_instance._type.name, initialize the attributes ina's__init__method. If you need it to work onaitself, put it in the metaclass.