3

我正在重构一个将各种日期格式(即 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 注册进行扩展,但我无法让它工作。

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

4

1 回答 1

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...
于 2021-10-12T00:02:25.580 回答