Python 유형 힌트: 반공변, 공변, 불변
그렇다면 공변량이란 무엇입니까?
A<: B이면 어디에서나 B를 A로 바꿀 수 있습니다.
여기서 B에 결합된 T는 C[T]라고 합니다.
A <: B => C[A] :> C[B]어디에서나 C[B]를 C[A]로 바꿀 수 있습니다. A <: B => C[A] <: C[B]어디에서나 C[A]를 C[B]로 바꿀 수 있습니다. 그러나이 상황을 일으키는 방법은 무엇입니까? 아래 예제 코드에서 설명하겠습니다. Sink / Source와 개념을 결합하십시오.
그들의 행동에 따라 우리는 두 종류의 객체를 정의했습니다.
매우 추상적이므로 아래 코드로 바로 넘어갑니다. 의견에 따라 수정하여 실험해 보십시오.
import abc
from typing import Generic, TypeVar
class Base:
def foo(self):
print("foo")
class Derived(Base):
def bar(self):
print("bar")
먼저
Base와 Derived. Derived가 Base,에 내재되어 있으므로 Derived <: Base.T_co = TypeVar('T_co', bound='Base', covariant=True)
class Source(Generic[T_co]):
@abc.abstractmethod
def generate(self) -> T_co: # Produce T_co!
pass
class SourceBase(Source[Base]):
def generate(self) -> Derived: # Produce T_co!
return Derived()
class SourceDerived(Source[Derived]):
def generate(self) -> Derived:
return Derived()
source: Source[Base] = SourceDerived()
source.generate()
#Try to uncomment lines below.
#source_derived: Source[Derived] = SourceBase()
#source_derived.generate()
이제
SourceDerived <: SourceBase 가 있습니다. covariant=True 를 제거하면 다음 경고가 표시됩니다.[Pyright reportGeneralTypeIssues] [E] Expression of type > "SourceDerived" cannot be assigned to declared type "Source[Base]"
TypeVar "T_co@Source" is invariant
"Derived" is incompatible with "Base"
covariant를 contravariant,로 수정하면 이렇게 됩니다. covariant 검사기 SourceDerived는 SourceBase를 사용하는 모든 곳에서 안전하게 사용할 수 있음을 알려줍니다. def generate(self) -> T_co: <- warining
pass
warining: [Pyright reportGeneralTypeIssues] [E] Contravariant type variable cannot be used in return type
TypeVar "T_co@Source" is contravariant
covariant 처럼 C[T_co]를 사용하는 곳을 확인하는 것 뿐만 아니라 C[T_co]에서 T_co를 반환하는 메서드를 확인하는 방법도 있습니다.다음으로
contravariant 예제를 살펴보겠습니다.T_contra = TypeVar('T_contra', bound='Base', contravariant=True)
class Sink(Generic[T_contra]):
@abc.abstractmethod
def consume(self, value: T_contra):
pass
class SinkBase(Sink[Base]):
def consume(self, value: Base):
value.foo()
class SinkDerived(Sink[Derived]):
def consume(self, value: Derived):
value.bar()
def other_func(self):
pass
base = Base()
derived = Derived()
sink_derived: Sink[Derived] = SinkBase()
#we can safely consumer
sink_derived.consume(base)
sink_derived.consume(derived)
#Try to uncomment this line.
#sink_derived.other_func()
여기에
SinkDerive <: SinkBase가 있습니다. 제거contravariant=True하면 경고가 표시됩니다.[Pyright reportGeneralTypeIssues] [E] Expression of type "SinkBase" cannot be assigned to declared type > "Sink[Derived]"
TypeVar "T_contra@Sink" is invariant
"Base" is incompatible with "Derived"
contravariant=True 정적 검사기에 Base를 Base 또는 Derive 유형으로 안전하게 사용할 수 있음을 알려줍니다. T_contra가 반공변이라는 주석을 달았지만 예를 들어 Sink[Derived]sink_derived.other_func() 메서드를 호출하면 오류가 발생합니다. 그럼에도 불구하고 contravariant가 covariant.와 반대라고 가정하는 것이 일반적입니다.대부분의 상황에서
contravariant 또는 covariant를 바로 추가할 필요가 없다고 생각합니다. 검사기가 불평할 때만 적절하게 사용되는 경우 이러한 제네릭 유형의 관계를 자세히 살펴봅니다. 그렇다면 이러한 힌트를 추가하는 것을 고려합니다.
Reference
이 문제에 관하여(Python 유형 힌트: 반공변, 공변, 불변), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/daniel1in/python-type-hint-contravariant-covariant-invariant-15lj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)