Reputation: 31652
I have two classes that inherit from the same parent:
class ChildOne(BaseSettings):
model_config = SettingsConfigDict(
extra="allow",
)
...
class ChildTwo(BaseSettings):
model_config = SettingsConfigDict(
extra="forbid",
)
...
I should be able to pass ChildOne and ChildTwo to anything that accepts BaseSettings right?
I cannot figure out how to get this to work and satisfy strict type checking.
I tried this, but the cast wipes out model_config set for the child and I'm still getting the two issues commented above the return statement
def my_func(model: BaseSettings) -> BaseSettings:
# Object of type "BaseSettings" is not callable
# Return type is unknown
return model()
# This cast seems to completely wipe out model_config
my_func(cast(ChildOne, BaseSettings))
my_func(cast(ChildTwo, BaseSettings))
After some googling this works, but I'm still not 100% why or if there is a cleaner way:
C = TypeVar("C", bound=BaseSettings)
def my_func(model: Type[C]) -> BaseSettings:
Do I have to explicitly tell the type checker that I want to accept any sub class of BaseSettings because it doesn't allow that automatically? Isn't that how basic class polymorphism is suppose to work?
This ^ also doesn't really work because when I try to access fields of C
inside my_func
I get:
Cannot access member "<Some field of ChildTwo|ChildOne>" for type "BaseSettings"
Member "<Some field of ChildTwo|ChildOne>" is unknown
I wasn't using generics correctly, I need to do:
C = TypeVar("C", bound=BaseSettings)
# Returns same type passed in, not BaseSettings type
def my_func(model: Type[C]) -> C:
I'm still confused as to why I need to use generics in the first place. Would I need to do something like this in C#/Java as well?
Upvotes: 0
Views: 1207
Reputation: 2353
Here you specify the type of model
as 'instance object of either BaseSettings class or any class, inherited from BaseSettings':
def my_func(model: BaseSettings) -> BaseSettings:
But it seems like you want to pass class itself (not an instance object of class). So, your second attempt is the right way to specify the type of model
:
C = TypeVar("C", bound=BaseSettings)
def my_func(model: Type[C]) -> BaseSettings:
But dont forget that in this case model
is not an instance object of class, but class itself. And it doesn't have attributes that you defined in your ChildOne
and ChildTwo
.
You need to create an instance object of this class to access attributes.
C = TypeVar("C", bound=BaseSettings)
def my_func(model: Type[C]) -> BaseSettings:
instance = model()
# instance.some_attribute
return instance
Or, do you want something like this?
def my_func(model: BaseSettings) -> BaseSettings:
# model.some_attribute = something
return model
res = my_func(ChildOne()) # passing instance
Upvotes: 0