Вот минимальный пример того, что мне нужно сделать:
from typing import Callable, Any
class Data:
pass
class SpecificData(Data):
pass
class Event:
pass
class SpecificEvent(Event):
pass
def detect_specific_event(data: SpecificData, other_info: str) -> SpecificEvent:
return SpecificEvent()
def run_detection(callback: Callable[[Data, Any], Event]) -> None:
return
run_detection(detect_specific_event)
Теперь я получаю предупреждение:
Expected type '(Data, Any) -> Event', got '(data: SpecificData, other_info: str) -> SpecificEvent' instead
Мне кажется, что это предупреждение не имеет смысла, поскольку SpecificData и SpecificEvent являются подтипами Data и Event соответственно, так что все должно быть в порядке. Есть ли способ сделать эту работу, как я ожидаю? Моя идея состоит в том, чтобы иметь возможность иметь что-то вроде:
class OtherSpecificData(Data):
pass
class OtherSpecificEvent(Event):
pass
def detect_other_event(data: OtherSpecificData, other_info: str) -> OtherSpecificEvent:
return OtherSpecificEvent()
run_detection(detect_other_event)
поэтому функция run_detection
является максимально общей. Прямо сейчас это дает то же предупреждение, что и выше.
run_detection
подразумевает, что переданный вызываемый объект должен иметь возможность работать сData
и всеми его подклассами, но затем вы передаете ему вызываемый объект, который говорит, что он не может работать сData
, он может работать только сSpecificData
. Например, предположим, чтоdetect_specific_event
использует атрибут вSpecificData
, которого нет в родительском классе. Ноrun_detection
сообщается, что ожидаемый обратный вызов этого не сделает; сказано, что он будет работать наData
и всех его подклассах. Тогда почему переданная функция требуетSpecificData
? - person alkasm   schedule 01.03.2020run_detection
может вызывать обратный вызов независимо от типа данных, то вы просите функцию требовать, чтобы вызываемый объект был более конкретным (работает только с базовым классом), чем вы хотите (работает с любым подклассом). Что касаетсяrun_detection
, отношения между классами не имеют значения. Простое решение — просто использоватьUnion
ваших подтипов. В противном случае ищите композицию вместо наследования. - person alkasm   schedule 01.03.2020run_detection
, о чем они спрашивали здесь, а не о том, как он получает данные. Если в следующий раз запустить только генераторSpecificData
, то он заработает. Но не в том случае, если он выдаетData
событий. - person JL Peyret   schedule 01.03.2020run_detection
является максимально общим, главное, что нужно здесь понять, это то, чтоrun_detection
ожидание вызываемого объекта в базовом классе более ограничительно, а не более общее. - person alkasm   schedule 02.03.2020