如何使用通用输入提示我的
__new__
实现?
所以我有一个可以存储
str
或decimal.Decimal
实例的类,它是输入str
或decimal.Decimal
类的子类。
此代码适用于 mypy 和 python:
from __future__ import annotations
import typing
import typing_extensions
import decimal
import random
T = typing.TypeVar('T', str, decimal.Decimal)
class StrOrDecimal(typing.Generic[T]):
@typing.overload
def __new__(cls, arg: decimal.Decimal) -> StrOrDecimalTyped.Decimal.StrOrDecimal[decimal.Decimal]:
...
@typing.overload
def __new__(cls, arg: str) -> StrOrDecimalTyped.Str.StrOrDecimal[str]:
...
# def __new__(cls, arg: typing.Union[str, decimal.Decimal]): does not work
def __new__(cls, arg): # works
if isinstance(arg, decimal.Decimal):
return super(cls, StrOrDecimalTyped.Decimal.StrOrDecimal).__new__(StrOrDecimalTyped.Decimal.StrOrDecimal, arg)
if isinstance(arg, str):
return super(cls, StrOrDecimalTyped.Str.StrOrDecimal).__new__(StrOrDecimalTyped.Str.StrOrDecimal, arg)
raise ValueError('Invalid value')
_StrOrDecimal = StrOrDecimal
# needed for mypy
class StrOrDecimalTyped:
class Str:
class StrOrDecimal(_StrOrDecimal[T], str):
pass
class Decimal:
class StrOrDecimal(_StrOrDecimal[T], decimal.Decimal):
pass
a_val = 'a'
a = StrOrDecimal(a_val)
print(a)
b_val = decimal.Decimal('1.2')
b = StrOrDecimal(b_val)
print(b)
choices: typing.List[typing.Union[str, decimal.Decimal]] = [a_val, b_val]
c_val = random.choice(choices)
c = StrOrDecimal(c_val)
try:
reveal_type(a)
reveal_type(b)
reveal_type(c)
except NameError:
typing_extensions.reveal_type(a)
typing_extensions.reveal_type(b)
typing_extensions.reveal_type(c)
但是如果使用这些签名中的任何一个:
def __new__(cls, arg: typing.Union[str, decimal.Decimal]):
def __new__(cls, arg: T):
我得到这个错误:
generic.py:19: 错误:“StrOrDecimal”的“__new__”参数 1 具有不兼容的类型“Type[generic.StrOrDecimalTyped.Decimal.StrOrDecimal[Any]]”;预期“类型 [generic.StrOrDecimal[T]]”
我该如何解决?