I would like to to pass class itself as an argument in the constructor. I know it is possible in Python but I am having problems understanding how should I write a proper typing annotation. Use case is the following:
In the constructor of class A
I want to pass a reference to some class X
(not an object of class X
) that inherits after BaseX
. Both X
and BaseX
come from a library. Apart from the reference to X
, constructor of A
accepts arguments that help build X
:
# Library
class BaseX:
def func():
print("Hey BaseX")
class X(BaseX):
def func():
print("X!")
# My client code
class A:
def __init__(arg x, arg y, layer: BaseX): # what should be the annotation of layer?
# construct BaseX object
self.layer = BaseX(x=x, y=y) # IDEs show x and y as unexpected arguments because they treat BaseX as an object and look into its __call__ func
A(5, 6, X)
I am unsure how can I express the annotation of layer so that it can be treated as a class and ensure its a derivative of BaseX
. I would also like to ask about some comment about whether this is a Pythonic way to do this.
Cheers!
You can indicate that a variable is a reference to a type with the annotation Type[BaseX]
(see Python docs on Type
). A variable annotated with Type[T]
holds any type that is a subtype of T
.
For your specific use case of "constructing an object of the specified type, which is a subtype of BaseX
", you can use more accurate annotations with the help of TypeVar
. For example:
T = TypeVar('T', bound=BaseX)
def construct(cls: Type[T], *args, **kwargs) -> T:
return cls(*args, **kwargs)
Here:
TypeVar('T', bound=BaseX)
defines a "type variable" that can be substituted with any type "bounded" by BaseX
, i.e., is a subtype of BaseX
.construct
function takes an argument cls
with annotation Type[T]
, indicating it's a reference to a subtype of BaseX
.T
, indicating the returned value is an instance of the subtype of BaseX
.