首页 > 编程问答 >如何让 python 类型在需要父类时将子类识别为有效类型?

如何让 python 类型在需要父类时将子类识别为有效类型?

时间:2024-07-30 14:33:41浏览次数:11  
标签:python python-typing

这是我需要做的一个最小示例:

from typing import Callable, Any


class Data:
    pass


class SpecificData(Data):
    pass


class Event:
    pass


class SpecificEvent(Event):
    pass


def detect_specific_event(data: SpecificData, other_info: str) -> SpecificEvent:
    return SpecificEvent()


def run_detection(callback: Callable[[Data, Any], Event]) -> None:
    return


run_detection(detect_specific_event)

现在我收到警告:

Expected type '(Data, Any) -> Event', got '(data: SpecificData, other_info: str) -> SpecificEvent' instead 

对我来说,这个警告似乎没有意义,因为 SpecificData 和 SpecificEvent 分别是 Data 和 Event 的子类型,所以一切都应该很好。有没有办法让这个工作如我所期望的那样?我的想法是能够有类似的东西:

class OtherSpecificData(Data):
    pass


class OtherSpecificEvent(Event):
    pass


def detect_other_event(data: OtherSpecificData, other_info: str) -> OtherSpecificEvent:
    return OtherSpecificEvent()

run_detection(detect_other_event)

所以 run_detection 功能尽可能通用。现在这给出了与上面相同的警告。


你遇到的问题是类型提示中的 协变 逆变 。在你的例子中,你想将一个接受 SpecificData Data 的子类)并返回 SpecificEvent Event 的子类)的函数传递给一个期望接受 Data 并返回 Event 的函数的函数。

  • 协变: 函数的返回类型可以是更具体的类型,但不能是更通用的类型。例如,返回 SpecificEvent 可以接受为返回 Event ,但反之则不行。
  • 逆变: 函数的参数类型可以是更通用的类型,但不能是更具体的类型。例如,接受 Data 可以接受为接受 SpecificData ,但反之则不行。

你的代码中出现类型错误的原因是, Callable[[Data, Any], Event] 期望一个可以处理 任何 Data 子类型的函数,而你提供的函数只能处理 SpecificData

你可以使用 类型变量 类型约束 来解决这个问题,使其更加通用:

from typing import Callable, Any, TypeVar, Generic

TData = TypeVar('TData', bound=Data)
TEvent = TypeVar('TEvent', bound=Event)

class Data:
    pass

class SpecificData(Data):
    pass

class Event:
    pass

class SpecificEvent(Event):
    pass

def detect_specific_event(data: SpecificData, other_info: str) -> SpecificEvent:
    return SpecificEvent()

def run_detection(callback: Callable[[TData, Any], TEvent], data: TData, other_info: Any) -> TEvent:
    return callback(data, other_info)

run_detection(detect_specific_event, SpecificData(), "")

在这个改进的版本中,我们引入了两个类型变量 TData TEvent ,它们分别受限于 Data Event 。这允许 run_detection 函数接受任何接受 Data 子类型并返回 Event 子类型的函数。

现在,你可以定义其他数据和事件类型,并使用相同的 run_detection 函数:

class OtherSpecificData(Data):
    pass

class OtherSpecificEvent(Event):
    pass

def detect_other_event(data: OtherSpecificData, other_info: str) -> OtherSpecificEvent:
    return OtherSpecificEvent()

run_detection(detect_other_event, OtherSpecificData(), "")

标签:python,python-typing
From: 60447851

相关文章

  • 使用 Python + Beautiful Soup 抓取任何包含 5 个数字的字符串
    我住在德国,那里的邮政编码在大多数情况下都是5位数字。53525。我真的很想使用beautifulSoup从网站中提取该信息。我是Python/BeautifulSoup的新手,我不知道如何将“查找连续的每5个数字+“空格””翻译成Python语言。importrequestsimporturllib.re......
  • 如何测试 python 类型协议是另一个协议的子类?
    该问题的明显解决方案是使用issubclass,但这会引发TypeError(使用Python3.6.7),例如>>>fromtyping_extensionsimportProtocol>>>classProtoSubclass(Protocol):...pass...>>>issubclass(ProtoSubclass,Protocol)Traceback(mos......
  • Python:指定与继承一起使用的类方法的返回类型
    我一直在尝试了解如何在Python中指定类方法的返回类型,以便即使对于子类也能正确解释它(例如在我的Sphinx文档中)。假设我有:classParent:@classmethoddefa_class_method(cls)->'Parent':returncls()classChild(Parent):pass什么如......
  • python使用SMTP功能发送邮件
    网页格式发送for_email.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><style>h1{color:brown;}p{margin:5px;color:purple......
  • python之代码简化式(列表、字典生成式,递归函数,迭代器(iter)和生成器(yield)、匿名函数(
    文章目录前言1、列表、字典生成式2、递归函数2.1python中代码的递归深度(扩展)3、拓展:迭代器和生成器3.1迭代器(iter)3.2生成器(yield)4、匿名函数(lambda)4.1map函数4.2reduce函数(较少使用)4.3filter函数前言本文主要讲解一些简化代码格式的一些方法,方便大家更好的......
  • Python:在 Protocol 和 TypedDict 之间共享类型注释
    举这个简单的例子:from__future__importannotationsimporttypingastclassMyType:def__init__(self,s:str,i:int)->None:self.s=sself.i=iclassMyProto(t.Protocol):s:stri:intclassMyDict(t.TypedDict):......
  • PIL 和 python 静态类型
    我有一个函数参数,它可以接受图像的多种类型:defsomefunc(img:Union[np.array,Image,Path,str]):PILImage在这种情况下抛出以下异常:TypeError:Union[arg,...]:eachargmustbeatype.Got<module'PIL.Image'from...进一步检查图像对象后这才有......
  • 学会用Python爬取小说网站,想看什么就爬什么,广告也不用看了~
    今天以爬取笔趣阁小说网站为例,练习Python爬虫技术。通过这个爬虫,可以完成批量爬取一本小说的所有章节,并将所有章节内容按顺序保存到一个txt文档内,下面我们就开始吧。首先,百度搜索“笔趣阁”,发现有很多网站都叫笔趣阁。我们可以随便挑选一个网站尝试,本文我以‘https://......
  • 计算机毕业设计django+vue《Python数据分析》的教学系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在当今数字化时代,数据分析已成为各行各业不可或缺的技能之一,而Python作为数据分析领域的首选语言,其重要性日益凸显。然而,传统的教学模式在......
  • 如何将多个变量分配给 python 函数中的单个参数?
    我正在尝试编写一个程序,如果可能的话,它需要一个三项式并对其进行因式分解。每当用户输入A、B和C时,三项式应该通过Factor(product,summation)函数获取,但我似乎无法弄清楚如何将A和C分配给乘积arg,将B分配给我尝试在函数外部声明不同的变量,product=(a*c)和summati......