Я пытаюсь напечатать подсказку о частичном применении конструктора, который полностью применяется после предоставления экземпляра «tag».Это реализуется через класс-оболочку, который хранит конструктор и любые частично примененные аргументы.Поскольку оболочка предназначена для нескольких типов, она должна принимать переменную *args
.
. Это создает два случая, которые отличаются аргументами, которые они принимают:
- Применить:
(tag: Tag, ...) -> Cls
- Store:
(...) -> Partial[Cls]
Примечательно, что в случае 2. может быть или не быть получен первый параметр.Оба пересекаются в своей арности, так как они разнообразны.Это просто реализовать.Я попытался напечатать эти подсказки, используя @overload
:
from typing import TypeVar, Generic
#: the class to partially construct
Cls = TypeVar('Cls')
class Tag:
"""Instances of this class complete the partial application"""
class Partial(Generic[Cls]):
"""Partially construct ``ctor`` until a :py:class:`~.Tag` is applied"""
def __init__(self, ctor: Type[Cls], *args):
self.ctor = ctor
self.args = args
# type hints
@overload
def __call__(self, tag: Tag, *args) -> Cls:
...
@overload
def __call__(self, *args) -> 'Partial[Cls]':
...
# implementation
def __call__(self, *args):
if args and isinstance(args[0], Tag):
return self.ctor(args[0], *self.args, *args[1:])
return Partial(self.ctor, *self.args, *args)
Однако ни mypy, ни PyCharm не довольны этим (PyCharm на данный момент нуждается в явном вызове метода, но это не моя проблема),Расширение второй перегрузки с явным не тегом (tag: Any, ...) -> Partial[Cls]
не решает проблему.Оба инструмента либо сообщают о несоответствии типов, о несовместимой перегрузке, либо возвращаются к Any
или Union
.
. Любая помощь при подсказке типов это правильно.
Типпример кода проверки:
class VariadicString(str):
def __new__(cls, *args):
return str(args)
a = RecursivePartial(VariadicString, 1, 2, 3)
b = a(4, 5, 6)
c = b(Tag(), 7, 8, 9)
reveal_locals() # absent for PyCharm
mypy
правильно определяет типы a
, b
и c
, но отклоняет программу из-за несовместимого перекрытия перегрузок:
test.py:17: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
test.py:38: error: Revealed local types are:
test.py:38: error: a: test.Partial[test.VariadicString*]
test.py:38: error: b: test,Partial[test.VariadicString*]
test.py:38: error: c: test.VariadicString*
PyCharm не отклоняет программу, но ошибочно определяет c
как Union
из обоих типов возврата:
a: Partial[VariadicString]
b: Partial[VariadicString]
c: Union[VariadicString, Partial[VariadicString]]