简体   繁体   中英

Can I type hint a subset of a Union in Python?

Usecase

I'd like a heterogenous queue to which producers can register at runtime. This would be for use in an Elm-style tui system. Thus, libraries could provide various registration functions for users, for hhtp requests etc. The question is, what should the signature of those functions be?

I want the user to be able to declare to the type system what kind of events they'd like to handle: Queue[Union[...]] , but also registration functions to accept any queue which has T as a Union member . Is that possible to express?

Full example

from queue import Queue
from typing import Union


def register_str_source(queue: "Queue[str]"): ...
def register_int_source(queue: "Queue[int]"): ...


queue: "Queue[Union[str, int]]" = Queue()

# Argument 1 to "register_str_source" has incompatible type "Queue[Union[str, int]]"; expected "Queue[str]"
register_str_source(queue)

# Argument 1 to "register_int_source" has incompatible type "Queue[Union[str, int]]"; expected "Queue[int]"
register_int_source(queue)

while event := queue.get(): # Exhaustive types are desirable here
    if isinstance(event, str):
        print(event)  # One may choose to register to additional events when handling this one
    elif isinstance(event, int):
        print(event)

Notes

I've tried:

  • Union[str, ...] . This is invalid
  • Using a bare Queue in the register_* functions. This doesn't catch a Queue.put of the wrong type within that scope.
  • Could there be a use for TypeVar s and Protocol s here?

You might be able to do this using a contravariant generic class that wraps Queue.

https://mypy.readthedocs.io/en/stable/generics.html#variance-of-generic-types

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM