PEP-526(https://peps.python.org/pep-0526/#class-and-instance-variable-annotations)에 따르면
ClassVar 인자에는 중첩 깊이와 관계없이 타입 변수가 들어갈 수 없습니다. T가 타입 변수라면 ClassVar[T]도 ClassVar[List[Set[T]]]도 유효하지 않습니다.
이 제약은 왜 있는 건가요? PEP에는 설명이 없는데, Typing github 기록에 답이 있을지도 모르겠네요…
멤버 두 개를 가진 제네릭 베이스 클래스에 타입을 붙이다가 이 문제를 만났어요. 하나는 특정 타입의 인스턴스를 담는 인스턴스 속성이고, 다른 하나는 그 인스턴스의 타입을 담는 클래스 속성이에요:
class _TransportBase[Conn: (httpx.Client, httpx.AsyncClient), Cred: httpx.Auth](ABC):
base_url: str
connection: Conn
_credential: Cred
_credential_type: ClassVar[Type] # intended as ClassVar[Type[Cred]]
@property
def credential(self) -> Cred:
return self._credential
@credential.setter
@abstractmethod
def credential(self, incoming: Any):
if not isinstance(incoming, self._credential_type):
self._credential = self._credential_type(incoming)
else:
self._credential = incoming
ClassVar가 이렇게 제한되어 있으면 이 속성이 클래스 수준이라는 것을 명시하거나, 그 타입과 _credential의 타입 사이 관계를 표현하거나 둘 중 하나를 포기해야 해요.
아직 초안이라 수정하면서 설계는 바뀔 거예요. 제안은 환영하지만 여기서 묻는 건 ClassVar에 관한 거예요.
영어에서 번역·원문 보기According to PEP-526 (https://peps.python.org/pep-0526/#class-and-instance-variable-annotations)
Note that no type variable may occur within a ClassVar argument, at any nesting depth: ClassVar[T] is invalid, as is ClassVar[List[Set[T]]], whenever T denotes a type variable.
What is the reason for that limitation? The PEP doesn't explain it; maybe the Typing github archives contain the answer…
I ran into this when annotating a generic base class with a pair of members, an instance attribute containing a typed instance and a class attribute containing that instance's type:
class _TransportBase[Conn: (httpx.Client, httpx.AsyncClient), Cred: httpx.Auth](ABC):
base_url: str
connection: Conn
_credential: Cred
_credential_type: ClassVar[Type] # intended as ClassVar[Type[Cred]]
@property
def credential(self) -> Cred:
return self._credential
@credential.setter
@abstractmethod
def credential(self, incoming: Any):
if not isinstance(incoming, self._credential_type):
self._credential = self._credential_type(incoming)
else:
self._credential = incoming
With ClassVar limited this way, I must choose between explicitly declaring this attribute class-level and showing how its type relates to the type of _credential.
This early design is bound to change during revision. I'd welcome suggestions, though the question I'm asking here concerns ClassVar.