공유 된 임의 유형으로 결합 된 추상 클래스에 대한 유형 주석

플로리안 브루 커

(저는 Python의 유형 주석 및 mypy에 익숙하지 않으므로 XY 문제가 발생하지 않도록 내 문제를 자세히 설명하고 있습니다)

임의이지만 고정 된 유형의 값을 교환하는 두 개의 추상 클래스가 있습니다.

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Generic, TypeVar


T = TypeVar('T')  # result type


class Command(ABC, Generic[T]):
    @abstractmethod
    def execute(self, runner: Runner[T]) -> T:
        raise NotImplementedError()


class Runner(ABC, Generic[T]):
    def run(self, command: Command[T]) -> T:
        return command.execute(self)

이 인터페이스의 구현에서 Command하위 클래스는 내 Runner하위 클래스 의 속성에 액세스해야합니다 (명령이 다른 기능을 가진 실행기에 적응할 수 있다고 상상해보십시오).

class MyCommand(Command[bool]):
    def execute(self, runner: Runner[bool]) -> bool:
        # Pseudo code to illustrate dependency on runner's attributes
        return runner.magic_level > 10


class MyRunner(Runner[bool]):
    magic_level: int = 20

이것은 예상대로 작동하지만 mypy를 만족시키지 않습니다.

mypy_sandbox.py:24: error: "Runner[bool]" has no attribute "magic_level"  [attr-defined]

분명히 mypy는 정확합니다. magic_level속성은에 정의되어 MyRunner있지만에 정의되어 있지 않습니다 Runner(에 대한 인수 유형 execute). 따라서 인터페이스가 너무 일반적입니다. 명령은 러너와 함께 작동 할 필요가없고 일부 러너에서만 작동합니다. 따라서 Command지원되는 러너 클래스를 캡처하기 위해 두 번째 유형 var에서 제네릭을 만들어 보겠습니다 .

R = TypeVar('R')  # runner type
T = TypeVar('T')  # result type


class Command(ABC, Generic[T, R]):
    @abstractmethod
    def execute(self, runner: R) -> T:
        raise NotImplementedError()


class Runner(ABC, Generic[T]):
    def run(self, command: Command[T, Runner[T]]) -> T:
        return command.execute(self)


class MyCommand(Command[bool, MyRunner]):
    def execute(self, runner: MyRunner) -> bool:
        # Pseudo code to illustrate dependency on runner's attributes
        return runner.magic_level > 10


# MyRunner defined as before

이것은 mypy를 만족하지만 코드를 사용하려고하면 mypy가 다시 불평합니다.

if __name__ == '__main__':
    command = MyCommand()
    runner = MyRunner()
    print(runner.run(command))
mypy_sandbox.py:35: error: Argument 1 to "run" of "Runner" has incompatible type "MyCommand"; expected "Command[bool, Runner[bool]]"  [arg-type]

이번에는 오류를 이해하지 못합니다. MyCommandis a subclass of Command[bool, MyRunner], MyRunneris a subclass of Runner[bool], so is MyCommandin compatible with Command[bool, Runner[bool]]?

그리고 mypy가 만족 스러웠다면 mypy 불평없이 (에 묶여 있지 않기 때문에 ) "다른 값"을 사용 Command하는 Runner서브 클래스를 가진 서브 클래스를 구현할 수있을 것입니다 . 시도 했지만 또 다른 오류가 발생합니다.TRTR = TypeVar('R', bound='Runner[T]')

error: Type variable "mypy_sandbox.T" is unbound  [valid-type]

위에서 설명한 확장이 가능하지만 올바르게 유형 검사되도록하려면 어떻게 유형 주석을 달 수 있습니까?

미스터 미야기

현재 주석은 실제로 모순입니다.

  • Runner단지 수 Command의 형식이야 Command[T, Runner[T]].
  • execute메서드 Command[bool, Runner[bool]]모든 Runner[bool] .
  • execute메서드는 MyCommand" Runner[bool] 가있는magic_level " 만 허용합니다 .

따라서 MyCommand는 a Command[bool, Runner[bool]]가 아닙니다 . " Runner[bool] 없이magic_level " 허용하지 않습니다 . 이로 인해 MyPy는 그 이유가 더 일찍 발생하더라도 대체를 거부합니다.


이 문제는 R의 자체 유형으로 매개 변수화하여 해결할 수 있습니다 Runner. 이렇게하면 baseclass에 의한 Runner매개 변수화 Command방지 하고 대신 실제 하위 유형의해 매개 변수화합니다 . Runner[T]Runner[T]

R = TypeVar('R', bound='Runner[Any]')
T = TypeVar('T')  # result type

class Command(ABC, Generic[T, R]):
    @abstractmethod
    def execute(self, runner: R) -> T:
        raise NotImplementedError()


# Runner is not generic in R
class Runner(ABC, Generic[T]):
    # Runner.run is generic in its owner
    def run(self: R, command: Command[T, R]) -> T:
        return command.execute(self)

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

추론 된 표현식 유형에 의해 재정의 된 유형 주석

분류에서Dev

사용 된 유형 / 클래스에 대한 CodeCompileUnit 분석

분류에서Dev

Python 유형 주석 : 상속 된 메서드의 반환 유형

분류에서Dev

상속 된 클래스로 파이썬 클래스의 유형 결정

분류에서Dev

약한 유형 검사 및 런타임 유형 검사를위한 코드 생성 부족으로 인해 유형 스크립트의 잘못된 결과

분류에서Dev

주석을 사용하지 않고 동적으로 인스턴스화 된 클래스의 유형을 추론하는 방법은 무엇입니까?

분류에서Dev

파이썬 클래스의 메서드에 하위 클래스로 정의 된 유형으로 주석을 달 수 있습니까?

분류에서Dev

결합 된 상속의 하위 클래스에 대한 CUBA 고유 속성이 지원되지 않음

분류에서Dev

열거 형으로 인덱싱 된 유형에서 유추 된 유형

분류에서Dev

Ocaml은 값에 대한 근접성으로 유추 된 유형을 명확하게합니다.

분류에서Dev

JPA : TypedQuery는 상속 된 유형에 대한 결과를 얻지 못합니다.

분류에서Dev

라켓의 클래스에 유형 주석 추가

분류에서Dev

GraphQL : 경고 : 실패한 prop 유형 :`StaticQuery`에 제공된`object` 유형의 잘못된 prop`query`, 예상되는`string`

분류에서Dev

TypeScript에서 식별 된 결합에 대한 인수를 기반으로 반환 유형을 자동으로 추론합니다.

분류에서Dev

혼합 된 일반 특성에 대한 유형 추론

분류에서Dev

더 높은 종류의 클래스에 대한 자체 유형 주석

분류에서Dev

Typescript 오류 : 클래스 유형에서 개인으로 정의 된 속성이 인터페이스 유형에서 공용으로 정의 됨

분류에서Dev

C ++의 "불완전한 유형 오류"가 중첩 된 클래스에 대해 유지되지 않는 이유

분류에서Dev

IIFE에 정의 된 유형으로 WebStorm 유형 검사

분류에서Dev

내부 유형으로 매개 변수화 된 클래스에서 상속

분류에서Dev

비 유형 템플릿 매개 변수의 추론 된 클래스 유형에 대한 자리 표시자가 C ++ 20 기능입니까?

분류에서Dev

특정 유형의 컬렉션에 대한 유형 주석

분류에서Dev

주어진 BNF 유사 형식으로 정의 된 트리 구조를 구문 분석하기위한 Python Regex

분류에서Dev

"추상 유형 X는 값이있는 Query.user 필드에 대해 런타임시 객체 유형으로 해석되어야합니다.

분류에서Dev

"추상 유형 X는 값이있는 Query.user 필드에 대해 런타임시 객체 유형으로 해석되어야합니다.

분류에서Dev

식별 된 공용체 유형에 대한 TypeScript 유틸리티 유형

분류에서Dev

로그 유형 기능에 대한 두 개의 쿼리에서 반환 된 결과 병합

분류에서Dev

T 이외의 유형 값으로 초기화 된 const T에 대한 참조

분류에서Dev

중첩 된 내부 클래스 : 상위 메서드에 액세스하고 중첩 된 클래스 유형의 변수를 노출합니다.

Related 관련 기사

  1. 1

    추론 된 표현식 유형에 의해 재정의 된 유형 주석

  2. 2

    사용 된 유형 / 클래스에 대한 CodeCompileUnit 분석

  3. 3

    Python 유형 주석 : 상속 된 메서드의 반환 유형

  4. 4

    상속 된 클래스로 파이썬 클래스의 유형 결정

  5. 5

    약한 유형 검사 및 런타임 유형 검사를위한 코드 생성 부족으로 인해 유형 스크립트의 잘못된 결과

  6. 6

    주석을 사용하지 않고 동적으로 인스턴스화 된 클래스의 유형을 추론하는 방법은 무엇입니까?

  7. 7

    파이썬 클래스의 메서드에 하위 클래스로 정의 된 유형으로 주석을 달 수 있습니까?

  8. 8

    결합 된 상속의 하위 클래스에 대한 CUBA 고유 속성이 지원되지 않음

  9. 9

    열거 형으로 인덱싱 된 유형에서 유추 된 유형

  10. 10

    Ocaml은 값에 대한 근접성으로 유추 된 유형을 명확하게합니다.

  11. 11

    JPA : TypedQuery는 상속 된 유형에 대한 결과를 얻지 못합니다.

  12. 12

    라켓의 클래스에 유형 주석 추가

  13. 13

    GraphQL : 경고 : 실패한 prop 유형 :`StaticQuery`에 제공된`object` 유형의 잘못된 prop`query`, 예상되는`string`

  14. 14

    TypeScript에서 식별 된 결합에 대한 인수를 기반으로 반환 유형을 자동으로 추론합니다.

  15. 15

    혼합 된 일반 특성에 대한 유형 추론

  16. 16

    더 높은 종류의 클래스에 대한 자체 유형 주석

  17. 17

    Typescript 오류 : 클래스 유형에서 개인으로 정의 된 속성이 인터페이스 유형에서 공용으로 정의 됨

  18. 18

    C ++의 "불완전한 유형 오류"가 중첩 된 클래스에 대해 유지되지 않는 이유

  19. 19

    IIFE에 정의 된 유형으로 WebStorm 유형 검사

  20. 20

    내부 유형으로 매개 변수화 된 클래스에서 상속

  21. 21

    비 유형 템플릿 매개 변수의 추론 된 클래스 유형에 대한 자리 표시자가 C ++ 20 기능입니까?

  22. 22

    특정 유형의 컬렉션에 대한 유형 주석

  23. 23

    주어진 BNF 유사 형식으로 정의 된 트리 구조를 구문 분석하기위한 Python Regex

  24. 24

    "추상 유형 X는 값이있는 Query.user 필드에 대해 런타임시 객체 유형으로 해석되어야합니다.

  25. 25

    "추상 유형 X는 값이있는 Query.user 필드에 대해 런타임시 객체 유형으로 해석되어야합니다.

  26. 26

    식별 된 공용체 유형에 대한 TypeScript 유틸리티 유형

  27. 27

    로그 유형 기능에 대한 두 개의 쿼리에서 반환 된 결과 병합

  28. 28

    T 이외의 유형 값으로 초기화 된 const T에 대한 참조

  29. 29

    중첩 된 내부 클래스 : 상위 메서드에 액세스하고 중첩 된 클래스 유형의 변수를 노출합니다.

뜨겁다태그

보관