Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PEP0484 Type Hinting: Annotating argument of given class, not instance

Let me explain with some sample, first.
Suppose there is a web API client module (MyAPIClient), a mapper class that converts arbitrary response into Python object (ObjectMapper), and a class that represents response object (User and Message).

class User(MyResponse):
    def __init__(self, status: int, id: int, name: str) -> None:
        super().__init__(status)
        self.id = int
        self.name = name

class Message(MyResponse):
    def __init__(self, status: int, id: int, text: str) -> None:
        super().__init__(status)
        self.id = int
        self.text = name

class ObjectMapper(object):
    def __init__(self, mapping_class: ???) -> None:
        self.mapping_class = mapping_class

    def map(self, obj) -> MyResponse:
        return self.mapping_class(**kwargs)

class MyAPIClient(object):
    def __init__(self, ...) -> None:
        pass

    def get_current_user(...) -> User:
        self.request("GET", "/current_user", ObjectMapper(User))

    def get_message(...) -> Message:
        self.request("GET", "/message", ObjectMapper(Message))

    def request(method: str, endpoint: str, mapper: ObjectMapper):
        res = requests.request(...)
        return json.loads(response.content.decode(), object_hook=mapper.map)

As shown in the sample above, ObjectMapper receives an argument named "mapping_class." This is NOT an instance of the class, but a class itself as shown in MyAPIClient#get_current_user and MyAPIClient#get_message. My question is how I should annotate this mapping_class in the ObjectMapper#__init__ which is currently marked as "???" in the sample above.

like image 537
Oklahomer Avatar asked Jan 03 '16 15:01

Oklahomer


People also ask

How do you write a hint in a class?

In a type hint, if we specify a type (class), then we mark the variable as containing an instance of that type. To specify that a variable instead contains a type, we need to use type[Cls] (or the old syntax typing. Type ). We need to add type hints for make_animal() .

What is the purpose of type hinting in Python?

PEP 484 introduced type hints — a way to make Python feel statically typed. While type hints can help structure your projects better, they are just that — hints — and by default do not affect the runtime.

Should I use type hinting in Python?

Type hints work best in modern Pythons. Annotations were introduced in Python 3.0, and it's possible to use type comments in Python 2.7. Still, improvements like variable annotations and postponed evaluation of type hints mean that you'll have a better experience doing type checks using Python 3.6 or even Python 3.7.

Does Python enforce type hints?

Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types. As the name says, type hints just suggest types. There are other tools, which you'll see later, that perform static type checking using type hints.


Video Answer


2 Answers

Use Type to refer to classes themselves:

class ObjectMapper(object):
    def __init__(self, mapping_class: Type[MyResponse]) -> None:
        self.mapping_class = mapping_class

    def map(self, obj) -> MyResponse:
         return self.mapping_class(**kwargs)
like image 101
David Ross Avatar answered Oct 04 '22 11:10

David Ross


Class itself is callable, that returns instance of that class. Solution can be:

mapping_class: Callable[..., MyResponse]
like image 27
Mikhail Gerasimov Avatar answered Oct 04 '22 09:10

Mikhail Gerasimov