【问题标题】:Type hints and @singledispatch: how do I include `Union[...]` in an extensible way?输入提示和@singledispatch:如何以可扩展的方式包含`Union [...]`?
【发布时间】:2020-05-11 03:19:34
【问题描述】:

我正在重构一个将各种日期格式(即 ISO 8601 字符串、datetime.datedatetime.datetime 等)转换为 Unix 时间戳的函数。

我希望新函数使用@singledispatch而不是类型检查,但我不知道如何保留以前函数的类型提示:

旧功能:使用类型检查

import datetime
from typing import Union


MyDateTimeType = Union[int, str, datetime.datetime, datetime.date, None]


# How do I retain this functionality with @singledispatch?
#                    ⬇️⬇️⬇️⬇️⬇️⬇️⬇️
def to_unix_ts(date: MyDateTimeType = None) -> Union[int, None]:
    """Convert various date formats to Unix timestamp..."""
    if type(date) is int or date is None:
        return date

    if type(date) is str:
        # Handle string argument...

    elif type(date) is datetime.datetime:
        # Handle datetime argument...

    elif type(date) is datetime.date:
        # Handle date argument...

新功能:使用@singledispatch

import datetime
from functools import singledispatch
from typing import Union


@singledispatch
def to_unix_ts(date) -> Union[int, None]:
    """Handle generic case (probably string type)..."""

@to_unix_ts.register
def _(date: int) -> int:
    return date


@to_unix_ts.register
def _(date: None) -> None:
    return date


@to_unix_ts.register
def _(date: datetime.datetime) -> int:
    return int(date.replace(microsecond=0).timestamp())


# etc...

我已经探索过像这样构建受支持的类型:

supported_types = [type for type in to_unix_ts.registry.keys()]
MyDateTimeType = Union(supported_types)  # Example, doesn't work

...这样它就可以通过未来的@singledispatch 注册进行扩展,但我无法让它工作。

如何以可扩展的方式在@singledispatch 函数中添加Union[...] 样式类型提示?

【问题讨论】:

  • 如果您真的希望您的类型提示有价值,您必须手动完成。使用运行时动态生成的信息来注释某些内容有什么用处?
  • @juanpa.arrivillaga 我的 IDE 的自省经常在我输入时捕获输入错误;)它在类似的运行时场景中智能地组合类型,例如类继承,正如您所期望的那样。如果我没有忽略任何事情,那么也许我的问题与其说是语言问题,不如说是 IDE 实现?

标签: python type-hinting single-dispatch


【解决方案1】:

我认为这就是您要寻找的。请注意singledispatch 需要register(type(None)) 而不是register(None)。它不支持register(Union[a, b]),但您可以将多个register 装饰器应用于一个函数...

import datetime
from functools import singledispatch
from typing import Union

MyDateTimeType = Union[
    int,
    None,
    datetime.datetime,
    datetime.date
]

@singledispatch
def to_unix_ts(date: MyDateTimeType) -> Union[int, None]:
    raise NotImplementedError

@to_unix_ts.register(int)
@to_unix_ts.register(type(None))
def _(date: Union[int, None]) -> Union[int, None]:
    return date

@to_unix_ts.register(str)
def _(date: str):
    # Handle string argument...

@to_unix_ts.register(datetime.datetime)
def _(date: datetime.datetime):
    # Handle datetime argument...

@to_unix_ts.register(datetime.date)
def _(date: datetime.date):
    # Handle date argument...

【讨论】:

    猜你喜欢
    • 2022-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多