当前位置: 首页 > 知识库问答 >
问题:

类型提示中的子类

谯德元
2023-03-14

我希望允许使用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]。

如何在这里更改类型提示以接受?

根据PEP 484(“类型为特定参数类型的子类型的表达式也可用于该参数。”),我知道我的解决方案< code>(cls: A)应该可以工作?

共有3个答案

罗宪
2023-03-14

如果您希望您的函数只接受子类,您应该使用NewTypehttps://docs.python.org/3/library/typing.html#newtype,因为Type[A]也接受类本身,这并不总是需要的。

楚方伟
2023-03-14

如果我们查看typing模块中的Type描述,那么我们会看到以下文档:

一种特殊的构造,可用于注释类对象。

例如,假设我们有以下类:

 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 来纠正这种情况。然后在将 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)

希望这会有所帮助。

狄彬彬
2023-03-14

当您指定 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本身)的类对象。

 类似资料:
  • 问题内容: 我想允许使用Python 3进行类型提示,以接受某个类的子类。例如: 现在,当输入以下代码时: 我得到一个PyCharm IDE提示“期望的类型A,取而代之的是Type [B]。” 如何更改此处的类型提示以接受A的任何子类型? 据此(https://www.python.org/dev/peps/pep-0484/#type-definition- syntax ,“该类型的参数也接受

  • 问题内容: class Node: def append_child(self, node: Node): if node != None: self.first_child = node self.child_nodes += [node] 我该怎么办?因为当我运行它时,它说。 我应该只删除and实例在函数中检查它吗?但是,我该如何访问的属性(我希望它是类的实例)? 我不知道如何在Python,

  • 问题内容: 在PEP 484中 ,包含模块的类型提示已添加到Python 3中。在Python 2中有什么方法可以做到这一点?我能想到的就是有一个装饰器来添加到检查类型的方法中,但这将在运行时失败,并且不会像提示所允许的那样被较早地捕获。 问题答案: 根据 Python 2.7的建议语法和 定义类型提示的PEP 484中的 跨代码 ,存在与Python 2.7兼容的另一种语法。但是,它不是强制性的

  • 我试图在Python3.5中使用类型提示。1,代码如下: 我猜在解析类型A时,类型A还没有完全构造,这是范围界定的问题,但我不理解为什么这样的语法不正确。是否有其他方式来表达它,或者它只是一个非法的构造? 我想在基类中使用这个语法提示,它可以在树状层次结构中组成派生类。

  • 问题内容: 只是好奇是否有一种方法可以在netbeans中为常规变量提供类型提示,以便intellisense可以选择。我知道您可以针对类属性,函数参数,返回类型等执行此操作,但是我不知道如何针对常规变量执行此操作。在您拥有可以返回不同对象类型(例如服务定位符)的方法的情况下,这确实有帮助。 例如: 之后使用$ someService的地方,netbeans将提供在Some_Service类中定义

  • 怎么修改让下面的红线消失?