类型提示中的子类
Subclass in type hinting
我想允许类型提示使用 Python 3 接受某个 class 的子 classes。例如:
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 提示 'Expected type A, got Type[B] instead.'
如何在此处更改类型提示以接受 A 的任何子类型?
根据 PEP 484(“其类型是特定参数类型的子类型的表达式也被该参数接受。”),我明白我的解决方案 (cls: A)
应该有效吗?
当您指定 cls: A
时,您是在说 cls
需要类型 A
的 实例 。将 cls
指定为类型 A
(或其子类型)的 class 对象的类型提示使用 typing.Type
.
from typing import Type
def process_any_subclass_type_of_A(cls: Type[A]):
pass
来自class个对象的类型
:
Sometimes you want to talk about class objects that inherit from a
given class. This can be spelled as Type[C]
where C
is a class. In
other words, when C
is the name of a class, using C
to annotate an
argument declares that the argument is an instance of C
(or of a
subclass of C
), but using Type[C]
as an argument annotation declares
that the argument is a class object deriving from C
(or C
itself).
如果我们查看 typing
模块中的 Type
描述,那么我们会看到这些文档:
A special construct usable to annotate class objects.
For example, suppose we have the following classes::
class User: ... # Abstract base for User classes
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...
And a function that takes a class argument that's a subclass of
User and returns an instance of the corresponding class::
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)
At this point the type checker knows that joe has type 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)
希望这会有所帮助。
我想允许类型提示使用 Python 3 接受某个 class 的子 classes。例如:
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 提示 'Expected type A, got Type[B] instead.'
如何在此处更改类型提示以接受 A 的任何子类型?
根据 PEP 484(“其类型是特定参数类型的子类型的表达式也被该参数接受。”),我明白我的解决方案 (cls: A)
应该有效吗?
当您指定 cls: A
时,您是在说 cls
需要类型 A
的 实例 。将 cls
指定为类型 A
(或其子类型)的 class 对象的类型提示使用 typing.Type
.
from typing import Type
def process_any_subclass_type_of_A(cls: Type[A]):
pass
来自class个对象的类型 :
Sometimes you want to talk about class objects that inherit from a given class. This can be spelled as
Type[C]
whereC
is a class. In other words, whenC
is the name of a class, usingC
to annotate an argument declares that the argument is an instance ofC
(or of a subclass ofC
), but usingType[C]
as an argument annotation declares that the argument is a class object deriving fromC
(orC
itself).
如果我们查看 typing
模块中的 Type
描述,那么我们会看到这些文档:
A special construct usable to annotate class objects.
For example, suppose we have the following classes::
class User: ... # Abstract base for User classes class BasicUser(User): ... class ProUser(User): ... class TeamUser(User): ...
And a function that takes a class argument that's a subclass of User and returns an instance of the corresponding class::
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)
At this point the type checker knows that joe has type 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)
希望这会有所帮助。