32

I want to type hint the following function:

def get_obj_class(self) -> CLASS_TYPE: return self.o.__class__ 
  • CLASS_TYPE should denote classes.
  • 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?

1

3 Answers 3

23

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.)

Sign up to request clarification or add additional context in comments.

2 Comments

I really dislike the need to create a named TypeVar object everytime you want to construct a custom type. I think in my situation I'd rather stick to type. But thank you for introducing this
@nO_OnE_910 -- you could reuse the same TypeVar variable when defining your generic classes and functions. You might perhaps find that a bit less distasteful since you're introducing only a single named TypeVar object (that you then reuse) instead of one per each generic class or function.
16

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__ 

1 Comment

+ for simplicity, although typing.TypeVar seems like the proper solution
1

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.

2 Comments

Why typing.Type and not just type?
@nO_OnE_910 I prefer to use the typing module to keep a coherent style. Most of my returns are typing.X, so it just seems more natural for me

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.