programing

형식 암시의 하위 클래스

linuxpc 2023. 6. 20. 21:24
반응형

형식 암시의 하위 클래스

Python 3을 사용하여 특정 클래스의 하위 클래스를 허용하는 유형 암시를 허용하고 싶습니다.예:

class A:
    pass

class B(A):
    pass

class C(A):
    pass

def process_any_subclass_type_of_A(cls: A):
    if cls == B:
        # do something
    elif cls == C:
        # do something else

이제 다음 코드를 입력할 때:

process_any_subclass_type_of_A(B)

PyCharm IDE 힌트 '예상 유형 A, 대신 유형 [B]를 받았습니다.'

A의 하위 유형을 받아들이려면 여기서 유형 암시를 변경하려면 어떻게 해야 합니까?

PEP 484에 따르면 ("특정 인수 유형의 하위 유형인 표현식도 해당 인수에 사용할 수 있습니다.") 저는 제 솔루션을 이해합니다.(cls: A)효과가 있을까요?

지정할 때cls: A그렇다는 말씀이시군요cls유형의 인스턴스를 예상합니다.A지정할 유형 힌트cls유형에 대한 클래스 개체로A(또는 해당 하위 유형)는 를 사용합니다.

from typing import Type
def process_any_subclass_type_of_A(cls: Type[A]):
    pass

원본 클래스 개체 유형:

지정된 클래스에서 상속되는 클래스 개체에 대해 이야기하고 싶을 때가 있습니다.이는 다음과 같이 철자할 수 있습니다.Type[C]어디에C클래스입니다.다시 말해서, 언제.C클래스의 이름입니다. 사용C인수에 주석을 달다 인수가 다음의 인스턴스임을 선언합니다.C(또는 하위 클래스의)C), 그러나 사용Type[C]인수 주석이 인수가 에서 파생되는 클래스 객체임을 선언함에 따라C(또는)C그 자체).

만약 우리가 그것을 본다면.Type의 설명typing모듈에서 다음 문서를 볼 수 있습니다.

클래스 개체에 주석을 달 수 있는 특수 구조입니다.

예를 들어 다음과 같은 클래스가 있다고 가정합니다.

 class User: ...  # Abstract base for User classes
 class BasicUser(User): ...
 class ProUser(User): ...
 class TeamUser(User): ...

그리고 User의 하위 클래스인 클래스 인수를 가져와서 해당 클래스의 인스턴스를 반환하는 함수:

 U = TypeVar('U', bound=User)
 def new_user(user_class: Type[U]) -> U:
     user = user_class()
     # (Here we could write the user object to a database)
     return user

 joe = new_user(BasicUser)

이 시점에서 유형 검사기는 Joe가 BasicUser 유형을 가지고 있다는 것을 알고 있습니다.

이를 바탕으로 PyCharm의 유형 암시 오류 문제를 재현하는 합성 사례를 상상할 수 있습니다.

from typing import Type, Tuple

class BaseClass: ...

class SubClass(BaseClass): ...
class SubSubClass(SubClass): ...

def process(model_instance: BaseClass, model_class: Type[BaseClass]) -> Tuple[BaseClass, BaseClass]:
    """ Accepts all of the above classes """
    return model_instance, model_class()


class ProcessorA:
    @staticmethod
    def proc() -> Tuple[SubClass, SubClass]:
        """ PyCharm will show an error 
        `Expected type 'tuple[SubClass, SubClass]', got 'tuple[BaseClass, BaseClass]' instead` """
        return process(SubClass(), SubClass)


class ProcessorB:
    @staticmethod
    def proc() -> Tuple[SubSubClass, SubSubClass]:
        """ PyCharm will show an error 
        `Expected type 'tuple[SubSubClass, SubSubClass]', got 'tuple[BaseClass, BaseClass]' instead` """
        return process(SubSubClass(), SubSubClass)

하지만 문서에는 다음과 같은 내용이 있습니다.Type사용함으로써 상황을 수정할 수 있다는 것.TypeVar와 함께bound논쟁.그리고 나서 그것을 사용하는 장소들.BaseClass는 형식으로 선언됩니다.

from typing import TypeVar, Type, Tuple

class BaseClass: ...

B = TypeVar('B', bound=BaseClass)

class SubClass(BaseClass): ...
class SubSubClass(SubClass): ...

def process(model_instance: B, model_class: Type[B]) -> Tuple[B, B]:
    """ Accepts all of the above classes """
    return model_instance, model_class()


class ProcessorA:
    @staticmethod
    def proc() -> Tuple[SubClass, SubClass]:
        return process(SubClass(), SubClass)


class ProcessorB:
    @staticmethod
    def proc() -> Tuple[SubSubClass, SubSubClass]:
        return process(SubSubClass(), SubSubClass)

이것이 도움이 되기를 바랍니다.

[A] 유형은 항상 필요한 것은 아닌 클래스 자체도 허용합니다.

함수가 하위 클래스만 허용하도록 하려면 다음과 같이 NewType을 사용해야 합니다.

class A:
    pass

B = NewType('B', A)

def foo(cls: Type[B]):
   ...

언급URL : https://stackoverflow.com/questions/46092104/subclass-in-type-hinting

반응형