Reputation: 597
I have a method which inspects and processes the source of arbitrary classes (classes only, not class instances or any other non-class types). The classes can be from any standard library, or 3rd party library, or user-defined classes.
But don't know of a correct way of annotating the type of the class argument using the typing
module. I don't think typing.Type
is the right one because it also applies to objects:
>>> class A: pass
>>> a = A()
>>> def test(cl: typing.Type) -> typing.Type:
... return type(cl)
>>> test(A)
>>> type
>>> isinstance(A, typing.Type)
>>> True
>>> test(a)
>>> type
>>> isinstance(A, typing.Type)
>>> False
>>> test('A')
>>> str
>>> isinstance(A, typing.Type)
>>> False
Should annotations work this way? Isn't the point that annotated arguments should restrict the calling of the method to recognise only the correct types of arguments?
Upvotes: 0
Views: 1760
Reputation: 63978
'Type' is indeed the right thing to use. For example, if you try type checking the following program using a type checker such as mypy...
from typing import Type
class A: pass
# To be even more precise, have the type signature be
# '(cls: Type[T]) -> Type[Type[T]]' where T is some TypeVar.
def test(cls: Type) -> Type:
return type(cls)
a = A()
test(A)
test(a)
test('A')
...you end up with the following errors, which I believe is what you were expecting:
test.py:13: error: Argument 1 to "test" has incompatible type "A"; expected "Type[Any]"
test.py:14: error: Argument 1 to "test" has incompatible type "str"; expected "Type[Any]"
Found 2 errors in 1 file (checked 1 source file)
If you are asking why these type hints are not being checked by Python itself and why you need to use a 3rd party type checker, see What are type hints in Python 3.5?.
Upvotes: 2