我有一个使用
typing.get_type_hints
的函数。我想向其添加
文档测试
但是,看起来 get_type_hints 无法解析 doctest 中定义的类型。
这是一个简化的示例:
import typing
def f(clazz):
"""
>>> class MyClass:
... my_field: 'MyClass'
>>> f(MyClass)
"""
typing.get_type_hints(clazz)
当使用
python3 -m doctest test.py
运行它时,它会抛出
NameError: name 'MyClass' is not defined
你遇到的是doctest的一个常见问题:doctest无法解析自身示例中定义的类型提示。这是因为doctest在运行代码之前不会执行整个文件,所以它不知道“MyClass”是什么。
幸运的是,有几种方法可以解决这个问题:
1. 使用__post_init__方法 (对于dataclass):
如果
MyClass
是一个dataclass,你可以利用
__post_init__
方法在类实例化之后调用
get_type_hints
。
from dataclasses import dataclass, fields
from typing import get_type_hints
@dataclass
class MyClass:
my_field: 'MyClass'
def __post_init__(self):
"""
>>> MyClass(MyClass()).my_field.__name__
'MyClass'
"""
hints = get_type_hints(self.__class__)
for field in fields(self):
# 使用hints[field.name]进行类型检查等操作...
2. 使用eval和locals():
你可以使用
eval
函数和
locals()
字典来动态地获取
MyClass
的定义。
import typing
def f(clazz):
"""
>>> class MyClass:
... my_field: 'MyClass'
>>> f(MyClass)
{'my_field': <class '__main__.MyClass'>}
"""
return typing.get_type_hints(eval(clazz.__name__, globals(), locals()))
3. 使用单独的函数定义类型提示:
将类型提示与函数逻辑分离,可以避免doctest的解析问题。
import typing
def get_my_class_hints():
"""
>>> get_my_class_hints()
{'my_field': <class '__main__.MyClass'>}
"""
class MyClass:
my_field: 'MyClass'
return typing.get_type_hints(MyClass)
def f(clazz):
# 在这里使用get_type_hints(clazz)
...
4. 使用unittest模块:
对于更复杂的测试场景,使用unittest模块可以提供更强大的功能和灵活性。
import unittest
import typing
class TestMyClass(unittest.TestCase):
def test_my_class(self):
class MyClass:
my_field: 'MyClass'
hints = typing.get_type_hints(MyClass)
self.assertEqual(hints['my_field'], MyClass)
if __name__ == '__main__':
unittest.main()
选择最适合你的方法取决于你的代码结构和测试需求。
标签:python,doctest From: 55937472