231

Couldn't seem to find a definitive answer. I want to do a type hint for a function and the type being some custom class that I have defined, called it CustomClass().

And then let's say in some function, call it FuncA(arg), I have one argument named arg. Would the correct way to type hint FuncA be:

def FuncA(arg: CustomClass):

Or would it be:

from typing import Type

def FuncA(Arg:Type[CustomClass]):
0

2 Answers 2

287

The former is correct, if arg accepts an instance of CustomClass:

def FuncA(arg: CustomClass):
    #     ^ instance of CustomClass

In case you want the class CustomClass itself (or a subtype), then you should write:

from typing import Type  # you have to import Type

def FuncA(arg: Type[CustomClass]):
    #     ^ CustomClass (class object) itself

Like it is written in the documentation about Typing:

class typing.Type(Generic[CT_co])

A variable annotated with C may accept a value of type C. In contrast, a variable annotated with Type[C] may accept values that are classes themselves - specifically, it will accept the class object of C.

The documentation includes an example with the int class:

a = 3         # Has type 'int'
b = int       # Has type 'Type[int]'
c = type(a)   # Also has type 'Type[int]'

Update 2024: Type is now deprecated in favour of type

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

4 Comments

@576i: iirc, you can also use a string. So def foo(bar: 'Qux') is equivalent to def foo(bar: Qux) except that it does not require loading the type immediately.
@cs95 Yes. All type hints are +3.7.
@WillemVanOnsem Useful! VS Code also supports it with Microsoft's Python Linter, Debugger using Pylance (instead of Jedi) python language server.
How do you type hint for a class that uses multiple inheritance or mixins? For example, what if I want to pass in a class that is both a sklearn BaseEstimator and a ClassifierMixin? Can type take both so def foo(a: type[BaseEstimator, ClassifierMixin]): and if so, does the order matter?
41

Willem Van Onsem's answer is of course correct, but I'd like to offer a small update. In PEP 585, type hinting generics were introduced in standard collections. For example, whereas we previously had to say e.g.

from typing import Dict

foo: Dict[str, str] = { "bar": "baz" }

we can now forgo the parallel type hierarchy in the typing module and simply say

foo: dict[str, str] = { "bar": "baz" }

This feature is available in python 3.9+, and also in 3.7+ if using from __future__ import annotations.

In terms of this specific question, it means that instead of from typing import Type, we can now simply annotate classes using the built-in type:

def FuncA(arg: type[CustomClass]):

1 Comment

This is the correct answer for Python 3.9 since use of typing.Type shown in Willem Van Onsem's answer is deprecated.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.