from collections.abc import Callable
from typing import Generic, TypeVar, TypeVarTuple
C = TypeVar("C")
T = TypeVar("T")
Ts = TypeVarTuple("Ts")
class Decorator1(Generic[T]):
def __init__(self, /, type: type[T]) -> None:
super().__init__()
def __call__(self, function: Callable[[C, T], None], /) -> Callable[[C, T], None]:
return function
class DecoratorNa(Generic[T]):
# Q: how to prevent "T" from becoming "object" here?
def __init__(self, /, *type: type[T]) -> None:
super().__init__()
def __call__(self, function: Callable[[C, T], None], /) -> Callable[[C, T], None]:
return function
class DecoratorNb(Generic[*Ts]):
def __init__(self, /, *types: *Ts) -> None:
super().__init__()
# Q: how to convert "*Ts" from "type[int], type[str]" to "int, str" here?
def __call__(
self, function: Callable[[C, *Ts], None], /
) -> Callable[[C, *Ts], None]:
return function
class MyClass:
# This is given and supposed to type-check:
@Decorator1(int)
def print_number(self, number: int) -> None: ...
@Decorator1(str)
def print_string(self, string: str) -> None: ...
# # This is supposed to error:
# @Decorator1(int)
# def print_another_string(self, string: str) -> None: ...
# This is supposed to type-check:
@DecoratorNa(int, str)
def print_number_and_string_a(self, number: int, string: str) -> None: ...
# This is supposed to type-check:
@DecoratorNb(int, str)
def print_number_and_string_b(self, number: int, string: str) -> None: ...
Конструктор Decorator принимает один (или несколько) типов во время выполнения (сравните PySide6.QtCore.Slot()), а декорированная функция должна принять один (или несколько) параметров этого типа.
Это отлично работает с одним типом, использующим type[T], но мне не удается найдите одно и то же для нескольких типов. Я попробовал *type: type[T], но результат равен T = object. Используя TypeVarTuple, я не понимаю, как преобразовать *Ts во что-то вроде ParamSpec. Я знаю typing.get_args, но не уверен, как это следует применять во время проверки типа.
(Я почти уверен, что формулировка вопроса не имеет смысла, но я еще не нашел лучшей.) У меня есть следующий код, который я хочу ввести -check: [code]from collections.abc import Callable from typing import Generic, TypeVar, TypeVarTuple
C = TypeVar("C") T = TypeVar("T") Ts = TypeVarTuple("Ts")
class Decorator1(Generic[T]): def __init__(self, /, type: type[T]) -> None: super().__init__()
# # This is supposed to error: # @Decorator1(int) # def print_another_string(self, string: str) -> None: ...
# This is supposed to type-check: @DecoratorNa(int, str) def print_number_and_string_a(self, number: int, string: str) -> None: ...
# This is supposed to type-check: @DecoratorNb(int, str) def print_number_and_string_b(self, number: int, string: str) -> None: ... [/code] Конструктор Decorator принимает один (или несколько) типов во время выполнения (сравните PySide6.QtCore.Slot()), а декорированная функция должна принять один (или несколько) параметров этого типа. Это отлично работает с одним типом, использующим type[T], но мне не удается найдите одно и то же для нескольких типов. Я попробовал *type: type[T], но результат равен T = object. Используя TypeVarTuple, я не понимаю, как преобразовать *Ts во что-то вроде ParamSpec. Я знаю typing.get_args, но не уверен, как это следует применять во время проверки типа.