As explained here, you can use Type:
from typing import Type
class X:
"""some class"""
def foo_my_class(my_class: Type[X], bar: str) -> None:
""" Operate on my_class """
Answer from roipoussiere on Stack OverflowAs explained here, you can use Type:
from typing import Type
class X:
"""some class"""
def foo_my_class(my_class: Type[X], bar: str) -> None:
""" Operate on my_class """
I could be wrong, as I haven't been getting down and dirty in Python 3.5 as yet, but looking at the documentation you should be able to do it with typing.Optional. A brief example.
>>> from typing import Optional
>>>
>>> class MyClass(object):
>>> def __init__(self):
>>> self.a = 1
>>>
>>> O = Optional[MyClass]
>>>
>>> def test(x: O) -> int:
>>> return x.a
>>>
>>> myclass = MyClass()
>>> print test(myclass)
1
Hope that helps.
Type-hinting with user defined classes
python - type hinting within a class - Stack Overflow
Type hints in class using class attributes
python - Type hints with user defined classes - Stack Overflow
I have two custom classes, one of which requires the other as an input argument.
class Authentication(object):
def __init__(self) -> None:
self.auth_data = self._resolve_auth()
class Data(object):
def __init__(self, authentication) -> None:
self.baseurl = authentication.baseurl
self.token = authentication.tokenI have the Authentication class defined in a seperate file in my project. So my question is, if I want to apply type-hinting to the Data class i.e.
def __init__(self, authentication: Authentication) -> None:
How do I go about doing this without having to import the Authentication class into my file which contains the Data class? It seems like overkill just to get proper type-hinting.
"self" references in type checking are typically done using strings:
class Node:
def append_child(self, node: 'Node'):
if node != None:
self.first_child = node
self.child_nodes += [node]
This is described in the "Forward references" section of PEP-0484.
Please note that this doesn't do any type-checking or casting. This is a type hint which python (normally) disregards completely1. However, third party tools (e.g. mypy), use type hints to do static analysis on your code and can generate errors before runtime.
Also, starting with python3.7, you can implicitly convert all of your type-hints to strings within a module by using the from __future__ import annotations (and in python4.0, this will be the default).
1The hints are introspectable -- So you could use them to build some kind of runtime checker using decorators or the like if you really wanted to, but python doesn't do this by default.
Postponed evaluation of annotations
PEP 563 introduced postponed evaluations in Python 3.7, stored in __annotations__ as strings. A user can enable this through the __future__ directive:
from __future__ import annotations
This makes it possible to write:
class C:
a: C
def foo(self, b: C):
...
This behaviour was originally planned to become mandatory in Python 4.0, then Python 3.10, but as of Python 3.13, it is still not mandatory. As of October 2024, no decision has been taken on when it will be mandatory.
I have a class I'm building as a learning tool. It's designed to be subclassed and so it's got some stuff built in to help with that. I'd like to assign an attribute within the class that could be changed when subclassing (or left as the default value), and want to use that to type hint the methods within the class, so that when subclassed it adjusts the type hints to suit the subclass.
class Coord:
"""A generic coordinate class"""
pass
class 2DCoord:
"""2D coordinates"""
pass
class Grid:
coord_type: type[Coord] = Coord
def some_method(arg: Self.coord_type) -> None:
pass
class 2DGrid(Grid):
coord_type = 2DCoordI want 2DGrid().some_method(arg) to expect a 2DCoord instance as its argument. Self.coord_type is highlighted as an invalid reference in PyCharm because typing.Self doesn't have a coord_type attribute. Is there a correct way to do this? Or is this meant to work but PyCharm isn't interpreting it correctly?
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
Cmay accept a value of typeC. In contrast, a variable annotated withType[C]may accept values that are classes themselves - specifically, it will accept the class object ofC.
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
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]):
Hello, Consider the code:
Class Spam:
@staticmethod
def make_spam(amount, animal_to_kill) -> Spam:
pass
And I'm getting NameError: name 'Spam' is not defined. I guess I cannot use a class name since it isn't fully definded. I know, I can live without fancy annotations, but...
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__