首页 > 编程问答 >mypy:方法的参数与超类型不兼容

mypy:方法的参数与超类型不兼容

时间:2024-07-27 04:02:20浏览次数:15  
标签:python python-typing mypy

看示例代码(mypy_test.py):

import typing

class Base:
   def fun(self, a: str):
       pass

SomeType = typing.NewType('SomeType', str)

class Derived(Base):
    def fun(self, a: SomeType):
        pass

现在 mypy 抱怨:

mypy mypy_test.py  
mypy_test.py:10: error: Argument 1 of "fun" incompatible with supertype "Base"

在这种情况下,我如何使用类层次结构并保持类型安全?

软件版本:

mypy 0.650 Python 3.7.1

我尝试过的:

import typing

class Base:
   def fun(self, a: typing.Type[str]):
       pass

SomeType = typing.NewType('SomeType', str)

class Derived(Base):
    def fun(self, a: SomeType):
        pass

但没有帮助。

一位用户评论道:“看起来你无法缩小覆盖方法中接受的类型的范围?”

但在这种情况下,如果我在基类签名中使用尽可能广泛的类型( typing.Any ),它也不应该工作。但确实如此:

import typing

class Base:
   def fun(self, a: typing.Any):
       pass

SomeType = typing.NewType('SomeType', str)

class Derived(Base):
   def fun(self, a: SomeType):
       pass

mypy 没有对上面的代码进行抱怨。


遇到的 mypy 错误是因为尝试在子类 Derived 缩小 fun 方法的参数类型。在类型提示中,子类型只能使参数类型更广泛(协变)或保持不变,而不能使其更狭窄(逆变)。

原因是类型安全。考虑以下代码:

class Base:
    def fun(self, a: str):
        print(a.upper())  # str 类型的方法

class Derived(Base):
    def fun(self, a: SomeType):
        print(a.lower())  # SomeType 类型的方法

b: Base = Derived()  # 多态性:b 是 Base 类型,但指向 Derived 对象
b.fun("HELLO")  

如果允许 Derived.fun 将参数类型缩小为 SomeType ,那么 b.fun("HELLO") 将会产生问题。 Base.fun 期望一个字符串并调用 str.upper() ,但它会收到一个 SomeType ,而 SomeType 可能没有 upper() 方法。

解决方案

  • 选项 1: 使 Base.fun 的参数类型更广泛:

```python from typing import Any

class Base: def fun(self, a: Any): pass

SomeType = typing.NewType('SomeType', str)

class Derived(Base): def fun(self, a: SomeType): pass ```

如所见,使用 Any 可以解决问题,因为它可以接受任何类型。但是,这可能会牺牲类型安全性。

  • 选项 2: 使用泛型和类型约束:

```python from typing import TypeVar, Generic

T = TypeVar('T', bound=str)

class Base(Generic[T]): def fun(self, a: T): pass

SomeType = typing.NewType('SomeType', str)

class Derived(Base[SomeType]): def fun(self, a: SomeType): pass ```

在这里,我们使用泛型 T 来表示参数类型,并使用 bound=str 限制 T 必须是 str 的子类型。这样, Derived 可以安全地将 T 指定为 SomeType

  • 选项 3: 重新考虑的设计。如果需要在子类中大幅度更改方法的参数类型,那么的类层次结构可能需要重新设计。

选择哪种方案取决于的具体需求和代码结构。

标签:python,python-typing,mypy
From: 54346721

相关文章

  • Python - 如何传递类对象的函数参数类型(打字)
    我想python3.7附带了(不确定),不仅可以将变量名传递给函数,还可以传递变量的类型。我想知道的是是否有可能传递特定类的类型。以同样的方式传递:deffoo_func(i:int)->None:pass如果我有一个类,让我们说:classfoo_class(object):pass我如何转换fo......
  • 使用 Python 构建简单 REST API
    使用Python构建简单RESTAPI1.概述本技术文档旨在指导开发者使用Python框架Flask构建一个基本的RESTAPI。通过学习本指南,您将掌握创建、读取、更新和删除(CRUD)操作的基本知识,并能够使用Python构建自己的API。2.安装依赖首先,您需要确保已安装Python和Flask......
  • Python——Pandas(第二讲)
    文章目录变量类型的转换Pandas支持的数据类型在不同数据类型间转换建立索引新建数据框时建立索引读入数据时建立索引指定某列为索引列将索引还原变量列引用和修改索引引用索引修改索引修改索引名修改索引值更新索引Series的索引和切片DataFrame的索引和切片选择列按......
  • 基于Python+Django的红色文化研学网站设计与实现
    ......
  • 【python】对网站进行请求-初识
    python实现对网站进行请求代码如下importrequestsdefget_data(url,headers=None,params=None,timeout=10):try:res=requests.get(url,headers=headers,params=params,timeout=timeout)res.raise_for_status()returnres.text......
  • 【python】Django初识-从未有如此美妙的开局
    Django初识python、Django安装与验证python安装Python官网https://www.python.org/Django安装pipinstallDjango验证python是否安装成功python--version验证Django是否安装成功python3-mdjango--version创建第一个Django项目项目创建与服务器启动打开cmd,输......
  • Python虚拟环境创建、激活、使用,项目依赖导出、安装requestments.txt
    Python虚拟环境通过命令行终端创建python虚拟环境:新建一个文件夹,可以专门用来存放虚拟环境,这里在D盘创建Python_Virtual_Environment_test文件夹然后在这里输入cmd按回车键进入命令行终端此时打开的位置就是当前的路径,当然也可以 cd一步步进入到目标路径创建环境......
  • 使用 Python 脚本自动生成报告
    使用Python脚本自动生成报告1.简介本文档介绍如何使用Python脚本自动生成报告。此脚本旨在简化报告生成过程,提高效率并减少人为错误。2.需求Python3.6或更高版本Pandas库Matplotlib库3.安装使用pip安装必要的库:pipinstallpandasmatplotlib4.脚本im......
  • 【和为 K 的子数组】python刷题记录
    这就到前缀和了。classSolution:defsubarraySum(self,nums:List[int],k:int)->int:#连续不能sortnum=len(nums)i=0j=i+1sm=0ret=0#j可以=是因为后面切片不包括jwhilej<=num:......
  • 嵌入式Python、ROS、SLAM、WebSocket和Node.js:智能巡逻监控安防机器人设计流程(代码示
    项目概述随着智能技术的发展,智能巡逻机器人在安防、监控和巡逻等领域的应用越来越广泛。本文将介绍一个结合嵌入式系统、机器人技术和后端开发的智能巡逻机器人。该机器人能够自主导航,实时检测异常情况(如火灾或入侵者),并将数据发送到后端服务器,以实现高效的监控和应急响应。主......