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

如何编写一个满足type. TextIO的类?

齐志勇
2023-03-14

在编写实现类文件接口的类时,我们可以从io模块继承一个抽象基类,例如TextIOBase,如图所示,使迭代器在Python中表现得像类文件对象。

另一方面,在类型注释中,我们应该使用从<code>类型派生的类。IO</code>(例如<code>TextIO</code>)表示这样的对象,如文件或类文件对象的类型提示所示?或io的类型检查问题。联合中的TextIOBase。

然而,这似乎并不像我预期的那样有效:

import io
import sys
import typing

class MyIO(io.TextIOBase):
    def write(self, text: str):
        pass

def hello(f: typing.TextIO):
    f.write('hello')

hello(sys.stdout)             # type checks
hello(open('temp.txt', 'w'))  # type checks
hello(MyIO())                 # does not type check

在这段代码上运行mypy时(使用Python 3.7.3和mypy 0.910),我们得到

错误:“hello”的参数 1 具有不兼容的类型“MyIO”;预期的“文本IO”

如何编写MyIO类,使其被接受为类型type. TextIO的函数参数(不只是使用typing.cast(type. TextIO,…))?

>

  • 使用type. TextIO作为基类是不可能的:

    当使用类 MyIO(键入。文本IO)

    错误:无法实例化抽象类“MyIO”,抽象属性“__enter__”、“__exit__”,...和“写行”(抑制 15 种方法)

    当使用类 MyIO(io.TextIOBase,打字。文本IO):

    错误:基类“IOBase”中“readlines”的定义与基类“IO”中的定义不兼容

    对于其他几种方法也是如此。

    覆盖__new__并注释键入。TextIO作为返回类型不起作用:

    def __new__(cls, *args, **kwargs) -> typing.TextIO:                        
        return super().__new__(cls, *args, **kwargs)
    

    结果是

    错误:不兼容的返回类型__new__(返回TextIO,但必须返回MyIO的子类型)
    错误:不兼容的返回值类型(得到MyIO,预期的TextIO)

    还是这已经可以工作了,而我使用的Python和/或mypy版本太旧了?但是,使用--python-version 3.83.93.10作为mypy的选项不会改变任何内容。

  • 共有2个答案

    万俟高峻
    2023-03-14

    我认为您的第一次尝试实际上是正确的,它只需要您实现所有抽象方法(如错误所述)。您不必将实际逻辑放在那里。以下类可以解决问题:

    import io
    from types import TracebackType
    from typing import Optional, Type, Iterator, AnyStr, Iterable, TextIO
    
    import sys
    import typing
    
    class MyIO(typing.TextIO):
        def __enter__(self) -> TextIO:
            pass
    
        def close(self) -> None:
            pass
    
        def fileno(self) -> int:
            pass
    
        def flush(self) -> None:
            pass
    
        def isatty(self) -> bool:
            pass
    
        def read(self, n: int = ...) -> AnyStr:
            pass
    
        def readable(self) -> bool:
            pass
    
        def readline(self, limit: int = ...) -> AnyStr:
            pass
    
        def readlines(self, hint: int = ...) -> typing.List[AnyStr]:
            pass
    
        def seek(self, offset: int, whence: int = ...) -> int:
            pass
    
        def seekable(self) -> bool:
            pass
    
        def tell(self) -> int:
            pass
    
        def truncate(self, size: Optional[int] = ...) -> int:
            pass
    
        def writable(self) -> bool:
            pass
    
        def writelines(self, lines: Iterable[AnyStr]) -> None:
            pass
    
        def __next__(self) -> AnyStr:
            pass
    
        def __iter__(self) -> Iterator[AnyStr]:
            pass
    
        def __exit__(self, t: Optional[Type[BaseException]], value: Optional[BaseException],
                     traceback: Optional[TracebackType]) -> Optional[bool]:
            pass
    
        def write(self, text: str):
            pass
    
    def hello(f: typing.TextIO):
        f.write('hello')
    
    hello(sys.stdout)             # type checks
    hello(open('temp.txt', 'w'))  # type checks
    hello(MyIO())                 # does not type check
    
    丌官浩旷
    2023-03-14

    使用<code>io。改为StringIO

    import io
    import sys
    import typing
    
    
    class MyIO(io.StringIO):
        def write(self, text: str):
            pass
    
    
    def hello(f: typing.TextIO):
        f.write("hello")
    
    
    hello(sys.stdout)             # type checks
    hello(open("temp.txt", "w"))  # type checks
    hello(MyIO())                 # type checks
     
    
     类似资料:
    • 本文向大家介绍请编写一个对象obj满足 obj=='a' && obj=='b' && obj=='c'相关面试题,主要包含被问及请编写一个对象obj满足 obj=='a' && obj=='b' && obj=='c'时的应答技巧和注意事项,需要的朋友参考一下

    • 我正处于Java的学习阶段。我想用Java编写一个程序,它可以读取一个Excel文件(.xlsx)。此文件有一些列和许多行。我想将数据写入另一个Excel文件(.xlsx),仅满足条件,而不是现有文件中的所有数据。 我的Excel工作表如下所示 我想只过滤那些带有代理Edelweiss的行,并把它放在另一个Excel表中。我知道如何使用Java将一个Excel中的所有数据复制到另一个Excel中。

    • 问题内容: 在Kubernetes代码中,该函数具有以下两种类型的结果列表: 该函数的最后一行是: 进口: 我通过在该import语句上运行而得到,对象在中定义: (并且我在这里在网上找到了相同的代码。) 地址运算符会创建一个指针…更具体地说,Go规范指出: 对于类型T的操作数x,地址操作&x生成指向 T的类型 T的指针。 和指针的类型不同于其基本类型: 指针类型表示指向给定类型的变量的所有指针的

    • 我们提供了邀约券和出行券两类券种,助力您的业务增长,升级客户服务。通过这两类券种,可实现客户到店体验、会员增值服务、积分礼品兑换等多种场景,并支持券面内容企业自由定制,真正地实现预算可控,帮助企业高效管理。

    • 问题内容: 我看到了许多生成器函数的示例,但是我想知道如何为类编写生成器。可以说,我想写斐波那契数列作为一个类。 输出: 为什么值没有打印出来?另外,我该如何为发电机编写代码? 问题答案: 您快要写完 Iterator 类了(我在答案末尾显示了Generator),但是每次使用调用对象时都会被调用,并返回一个generator对象。相反,要使您的代码以最少的更改和最少的代码行工作,请使用,这使您的

    • 如果对于树中的每个非叶节点,存储在该节点的数字小于或等于存储在其每个子节点的数字,则二叉树称为堆(或者,称为满足堆属性)。例如,下面的树满足heap属性,因为3≤ 5, 5 ≤ 8和5≤ 7. 另一方面,下面的树不满足堆属性,因为6不小于或等于5。 示例: 任何帮助都将得到认可。