jb.
jb.

Reputation: 23955

How to annotate a method that returns a specific type (or subtype)

Please consider this snippet of python 3.5 code:

class Foo:
    pass

class Bar(Foo):
   pass

class AbstractSomething: 

    def get_foobinator_type(self):  
        return Foo

I'd like to annotate (using PEP-0484 annotations) return value of get_foobinator_type method to say: "It returns a type, that is either a Foo or any subtype of it".

I din't find any sensible way to do it in Python. Here are approaches that are obviously wrong:

In Java terms I'd like to have method with signature like: Class<Foo> getFoobinatorType().

Upvotes: 1

Views: 486

Answers (3)

jb.
jb.

Reputation: 23955

Lately (in Python 3.5.2) a generic Type was introduced, so solution is:

class AbstractSomething: 

    def get_foobinator_type(self) -> typing.Type[Foo]:  
        return Bar

See: python docs.

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

As far as I understand, you really cannot. You're looking for a way to indicate the return type of a class; to check based on what the type of the class is, i.e its metaclass.

The problem with that is that a metaclass doesn't help a type checker evaluate what the inheritance of an object might be, if it's of type type it's alright.

Apart from that, and, not being sure what type-checker you use, mypy for example doesn't have support yet for custom metaclasses which you might use to group your objects in a more custom group.

The way I see it, you either don't annotate at all all, or, you change the implementation and annotate with Foo.

Upvotes: 2

Kostas Pelelis
Kostas Pelelis

Reputation: 1342

I think what you need is TypeVar from the typing module.

from typing import TypeVar

class Foo:
    pass

class Bar(Foo):
   pass

T = TypeVar('T', bound=Foo)

class AbstractSomething: 

    def get_foobinator_type(self) -> T:  
        return Foo

From the documentation of typing:

Alternatively, a type variable may specify an upper bound using bound=. This means that an actual type substituted (explicitly or implicitly) for the type variable must be a subclass of the boundary type, see PEP 484

Upvotes: 0

Related Questions