我在使用 doctest 和协程时遇到了一些麻烦...
def coroutine(func):
def start(*args, **kwargs):
cr=func(*args, **kwargs)
cr.next()
return cr
start.__name__=func.__name__
return start
@coroutine
def leader_tracking():
"""
Tracks 'leader' status - only returns transitions
>>> lt=leader_tracking()
>>> print lt.send(False)
>>> print lt.send(False)
"""
last_status=False
result=("nop", None)
while True:
status=(yield result)
if status!=last_status:
direction="up" if last_status==False else "down"
last_status=status
result=("tr", direction)
else:
result=("nop", None)
如果我使用通常的 doctest 脚手架:
if __name__=="__main__":
import doctest
doctest.testmod()
doctest 不显示任何内容,而如果我使用更强力的方法:
lt=leader_tracking()
print lt.send(True)
print lt.send(False)
print lt.send(False)
print lt.send(True)
print lt.send(True)
print lt.send(True)
print lt.send(True)
print lt.send(False)
我可以看到预期的结果:
('tr', 'up')
('tr', 'down')
('nop', None)
('tr', 'up')
('nop', None)
('nop', None)
('nop', None)
('tr', 'down')
doctest 我做错了什么?
请您参考如下方法:
doctest 模块查看存储在函数的 __doc__ 属性中的文档字符串。您的协程装饰器仅复制 __name__,因此文档字符串丢失并且 doctest 无法找到它。您可以手动分配 __doc__ 属性,但更好的方法是使用 functools 模块:
import functools
def coroutine(func):
@functools.wraps(func)
def start(*args, **kwargs):
cr = func(*args, **kwargs)
cr.next()
return cr
return start
functools.wraps 装饰器将 func 的所有各种元数据属性复制到包装函数 start 中,包括 docstring,以便 doctest将按预期工作。
另请注意,为了正常工作,您的 doctest 注释应包含预期的输出:
@coroutine
def leader_tracking():
"""
Tracks 'leader' status - only returns transitions
>>> lt=leader_tracking()
>>> print lt.send(True)
('tr', 'up')
>>> print lt.send(False)
('tr', 'down')
>>> print lt.send(False)
('nop', None)
"""
last_status = False
result = ("nop", None)
while True:
status = yield result
if status != last_status:
direction = "up" if last_status == False else "down"
last_status = status
result = ("tr", direction)
else:
result = ("nop", None)
