В следующем примере:
Код: Выделить всё
from typing import *
from dataclasses import dataclass
PARAMS = ParamSpec("PARAMS")
@dataclass
class Event:
field1: int
field2: bool
name: str
def get_name(self) -> str:
return self.name
class SomeCaller:
...
class Element:
...
class ClickEvent(Event):
def __init__(self, field1: int, field2: int, target: str):
super().__init__(field1=field1, field2=field2, name="click")
self.__target = target
@property
def target(self) -> str:
return self.__target
# The type hint in question
HANDLER = Callable[
[
Event,
PARAMS
], Union[Any, Coroutine]
]
def control(event: Event, *args, **kwargs) -> bool:
pass
def false_control(event: ClickEvent, *args, **kwargs) -> bool:
pass
async def async_function(event: Event, arg1: int, arg2: int, *args, **kwargs):
return 9
def function(event: ClickEvent, arg1: int, arg2: int, *args, **kwargs):
return 7
def other_function(event: Event, caller: SomeCaller, element: Element):
return 8
class EventHandlerWhatsit:
def __init__(self, handler: HANDLER):
self.__handler = handler
control_value = EventHandlerWhatsit(control)
false_control_value = EventHandlerWhatsit(false_control)
async_function_value = EventHandlerWhatsit(async_function)
function_value = EventHandlerWhatsit(function)
other_function_value = EventHandlerWhatsit(other_function)
def main():
print("This works")
if __name__ == "__main__":
main()
Все, что ему нужно указать, это «Что-то, что можно вызывать, если оно начинается с параметра, который является подклассом Event ». Имена не имеют значения. Я экспериментировал с определением HANDLER разными способами, например, определял *args и **kwargs как Tuple[Any, ...] и Dict[str, Any] (с необязательным и без него), с дополнительными параметрами и по-прежнему выдает те же виды предупреждений.
Я' Я застрял в Python 3.8 и редактирую в PyCharm, который показывает предупреждения.
Есть идеи?
РЕДАКТИРОВАТЬ >:
@Daniil Fajnberg и @SUTerliakov дали отличные ответы в комментариях:
Код: Выделить всё
HANDLER = Callable[
Concatenate[
Event,
PARAMS
], Union[Any, Coroutine]
]
Код: Выделить всё
Concatenate
Возьмите следующий недопустимый код:
Код: Выделить всё
def test_inner(arg: Callable[[str, int, P], Any]):
pass
def test_input(i: str, j: int, q: str = None, *args, **kwargs):
pass
def test_outer():
test_inner(test_input)
Предупреждение: ParamSpec и Concatenate были представлены в Python 3.10. Если вам необходимо использовать более старую версию из-за ограничений среды, используйте пакет typing_extensions, чтобы обеспечить эту функциональность.
Подробнее здесь: https://stackoverflow.com/questions/767 ... -in-python