如何理解 doctest 中的 “Got nothing” 错误提示

2026-06-03 127750 日常编程

当 doctest 报错 “got nothing”,意味着被测函数未产生任何可显示的输出(如返回值为 none 或未显式打印),而预期却有明确输出(如 private: 80),导致断言失败。

当 doctest 报错 “got nothing”,意味着被测函数未产生任何可显示的输出(如返回值为 none 或未显式打印),而预期却有明确输出(如 private: 80),导致断言失败。

在你的 best_apartment 方法中,doctest 期望看到类似 PRIVATE: 80 的输出,但实际运行后却提示 Expected: PRIVATE: 80\nGot nothing —— 这并非表示程序崩溃或静默退出,而是 Python 交互式环境(以及 doctest)默认不显示 None 的返回值

例如:

>>> def f(): return None
>>> f()  # 无任何输出
>>>
>>> def g(): return "hello"
>>> g()
'hello'

你的方法当前存在两个关键问题:

  1. 类型签名与行为矛盾:函数声明为 -> None,但 docstring 却要求“Return (one of) the apartment(s)...”,且 doctest 明确期望返回字符串(如 PRIVATE: 80)。这会导致类型检查工具(如 mypy)警告,更重要的是,doctest 会严格比对 print() 输出或表达式求值结果 —— 而 None 不会被打印。

  2. 空树逻辑未匹配预期:当 self.is_empty() 为真时,你 return None,但 doctest 示例中 bst 是通过 build_tree(apartments) 构建的(含 300 个公寓),理论上不应为空;然而若 build_tree 实现有缺陷(如未正确插入节点、根节点为 None),或 is_empty() 判断逻辑错误(如未覆盖边界情况),就可能意外触发 return None,最终导致 “Got nothing”。

✅ 正确修复方式如下:

  • 修正返回类型与实现一致性:将签名改为 -> Optional[str](需 from typing import Optional),并确保所有路径都返回有效字符串或明确处理空树;
  • 避免依赖 None 的隐式不输出行为:doctest 中的 >>> bst.best_apartment() 行测试的是表达式求值结果,不是 print() 输出。因此必须 return 预期字符串(如 f"{self.apartment.type}: {self.apartment.score}"),而非调用 print()(后者虽有输出,但返回值仍是 None,仍报 “Got nothing”);
  • 增强健壮性:即使非空树,也要防止 current_node.apartment 为 None(例如节点初始化不完整)。

改进后的参考实现:

from typing import Optional

def best_apartment(self) -> Optional[str]:
    """Return (one of) the apartment(s) with the best evaluation
    score in the BSTTree.
    >>> apartments = read_apartment_data("apartments.csv")[0:300]
    >>> bst = BSTTree()
    >>> bst.build_tree(apartments)
    >>> bst.best_apartment()
    'PRIVATE: 80'
    """
    if self.is_empty():
        return None  # 或 raise ValueError("Cannot find best apartment in empty tree")

    current_node = self
    while current_node.right is not None:
        current_node = current_node.right

    # 确保 apartment 属性存在且格式合法
    if not hasattr(current_node, 'apartment') or current_node.apartment is None:
        return None
    return f"{current_node.apartment.type}: {current_node.apartment.score}"

? 调试建议

  • 在 doctest 失败时,直接在 Python 交互式终端中逐行执行示例代码,观察真实返回值:
    >>> bst.best_apartment()  # 查看是否真返回 None
    >>> type(bst.best_apartment())
  • 检查 BSTTree.build_tree() 和 is_empty() 实现,确认树结构正确构建;
  • 使用 # doctest: +ELLIPSIS 或 # doctest: +NORMALIZE_WHITESPACE 等指令处理不确定输出(非本例所需,但值得了解)。

总之,“Got nothing” 是 doctest 的精准提示:它没收到任何可比对的返回值。解决核心在于让函数稳定返回预期类型的非 None 值,并保持文档、签名与实现三者一致。

如何理解 doctest 中的 “Got nothing” 错误及其修复方法

doctest报错“gotnothing”表示函数实际未产生任何可显示的输出(如返回none或无print),但测试用例却期望看到具体值(如'private:80'),本质是返回值与预期不匹配。 doctest报错“gotnothing”表示函数实际未产生任何可显示的输出(如返回none或无print),但测试用例却期望看到具体值(如'private:80'),本质是返回值与预期不匹配。 在你的b...

Python生成器yield关键字怎么理解_掌握惰性求值优化大内存处理

yield将函数变为生成器工厂,调用返回generator对象而非执行结果;与return的本质区别在于:return终止函数并丢弃局部变量,yield暂停函数并完整保留栈帧(含局部变量和执行位置),下次从yield下一行继续。 yield是什么,它和return有什么本质区别 yield不是“暂停函数”,而是把函数变成生成器工厂——调用它返回的是一个generator对象,不是执行结果。真正执行...

为什么Python中的sys.getsizeof结果不符合预期_理解Python对象的内存分配与容器机制

sys.getsizeof仅测量对象自身结构体大小,不包含其引用的子对象内存;真实总内存需用pympler.asizeof或tracemalloc分析。 sys.getsizeof不是“对象总内存”的测量函数,它只返回对象头+直接持有的数据结构的字节大小,对容器类、自定义类、嵌套引用几乎全部失效。 sys.getsizeof对列表/字典等容器只算“箱子本身”,不算“箱子里的东西” 列表在内存中实际...

深入理解JavaScript中Error类的继承与自定义错误处理

在JavaScript中,通过继承Error类创建自定义错误类型,能够实现更精细、更具可读性的错误处理。这种模式允许开发者使用instanceof操作符准确识别特定类型的错误,从而执行有针对性的恢复逻辑,避免了对通用Error对象进行模糊判断的弊端,是构建健壮应用的关键实践。在javascript应用程序开发中,错误处理是不可或缺的一环。内置的error对象及其子类(如typeerror、refe...

深入理解JavaScript中自定义错误类的必要性

在JavaScript中,通过继承Error类创建自定义错误类型(如InputError)是实现精确错误处理的关键实践。这种方法允许开发者利用instanceof操作符识别和区分不同类型的错误,从而执行有针对性的恢复逻辑,提高代码的健壮性、可读性和可维护性,而非仅仅依赖于通用的Error对象或解析错误消息。 为什么需要自定义错误类? 在应用程序开发中,错误处理是不可或缺的一部分。javascrip...

深入理解Go语言Map的迭代顺序及其内部机制

Go语言中的Map被实现为哈希表,其迭代顺序是未定义的,并且在Go1及后续版本中被强制随机化。这种随机化机制旨在防止开发者依赖Map的内部实现细节,确保代码的健壮性和可移植性。理解Map的内部结构及其迭代顺序的演变,对于编写高质量的Go程序至关重要。GoMap的内部实现 go语言中的map类型在运行时被实现为一个哈希表(hashmap)。这个哈希表的底层实现是基于c语言的,是go运行时的一部分。尽...

深入理解Go语言结构体中的接口嵌入与方法提升

Go语言支持结构体嵌入(anonymousfields),允许将接口或其他结构体类型直接嵌入到另一个结构体中,无需显式指定字段名。此时,被嵌入的类型名将自动作为字段名。这种机制不仅简化了结构体定义,更重要的是实现了方法的自动提升,使得外部结构体可以直接调用嵌入类型的方法,极大地增强了代码的复用性和灵活性。本文将详细探讨Go结构体中接口嵌入的原理、访问方式及注意事项。Go语言结构体嵌入(匿名字段)原...

深入理解CSS选择器:解决Django项目中图片样式不生效问题

本文旨在解决Django应用中CSS样式不应用于图片的常见问题。我们将探讨如何正确加载静态文件、利用浏览器开发者工具诊断样式问题,并深入理解CSS选择器的特异性与层级关系,从而精确地定位并应用样式到目标图片元素,确保项目视觉效果符合预期。在开发django应用时,开发者常会遇到css样式未按预期应用于页面元素,特别是图片的情况。这通常并非django框架本身的问题,而是与css选择器的使用、静态文...