1

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ですか?

4

1 に答える 1

6

__doc__doctest モジュールは、関数の属性に格納されている docstring を調べます。コルーチン デコレータは のみをコピー__name__するため、docstring が失われ、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

デコレーターは、docstring を含むfunctools.wrapsすべてのさまざまなメタデータ属性をfuncラッピング関数にコピーして、doctest が期待どおりに機能するようにします。start

また、正常に動作するためには、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)
于 2012-02-02T03:56:30.610 に答える