I want to type hint the following function:
def get_obj_class(self) -> CLASS_TYPE:
return self.o.__class__
CLASS_TYPE
should denote class
es.self.o
could be of any type determined at runtime.On a similar note, if I have a function f(cls: CLASS_TYPE)
which returns an instance of cls
, is there a way to type hint the return value appropriately?
In a type hint, if we specify a type (class), then we mark the variable as containing an instance of that type. To specify that a variable instead contains a type, we need to use type[Cls] (or the old syntax typing. Type ). We need to add type hints for make_animal() .
Type hints help you build and maintain a cleaner architecture. The act of writing type hints forces you to think about the types in your program. While the dynamic nature of Python is one of its great assets, being conscious about relying on duck typing, overloaded methods, or multiple return types is a good thing.
Python has a lot of built-in functions. The type() function is used to get the type of an object. When a single argument is passed to the type() function, it returns the type of the object. Its value is the same as the object.
The purpose of the Any type is to indicate to the type checker that a part of the program should not be checked. A variable (or function parameter) that is annotated with the Any type accepts any value, and the type checker allows any operation on it.
I'd recommend using a combination of TypeVar
, to indicate that your self.o
value could be any arbitrary type, and Type
, in the following way:
from typing import TypeVar, Type
T = TypeVar('T')
class MyObj:
def __init__(self, o: T) -> None:
self.o = o
def get_obj_class(self) -> Type[T]:
return type(self.o)
def accept_int_class(x: Type[int]) -> None:
pass
i = MyObj(3)
foo = i.get_obj_class()
accept_int_class(foo) # Passes
s = MyObj("foo")
bar = s.get_obj_class()
accept_int_class(bar) # Fails
If you want the type of o
to be even more dynamic, you could explicitly or implicitly give it a type of Any
.
Regarding your latter question, you'd do:
def f(cls: Type[T]) -> T:
return cls()
Note that you need to be careful when instantiating your class -- I don't remember what Pycharm does here, but I do know that mypy currently does not check to make sure you're calling your __init__
function correctly/with the right number of params.
(This is because T could be anything, but there's no way to hint what the constructor ought to look like, so performing this check would end up being either impossibly or highly difficult.)
For Python >=3.7, use type
(see also PEP 585):
def get_obj_class(self) -> type:
return self.o.__class__
For Python <3.7, use typing.Type
:
def get_obj_class(self) -> typing.Type:
return self.o.__class__
What about typing.Type
?
That seems to fit since __class__
should always return a type.
import typing
def test(t: object) -> typing.Type:
return t.__class__
class Dummy(object):
pass
test(Dummy())
To your second question: that should be a generic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With