19

次の python スクリプトがあるとします。

# dedupe.py
import re

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> dedupe_whitespace(r"Green\t\tGround")  # doctest: +REPORT_NDIFF
    'Green\tGround'
    """
    for w in spacechars:
        s = re.sub(r"("+w+"+)", w, s)
    return s

この関数は、Python インタープリター内で意図したとおりに機能します。

$ python
>>> import dedupe
>>> dedupe.dedupe_whitespace('Purple\t\tHaze')
'Purple\tHaze'
>>> print dedupe.dedupe_whitespace('Blue\t\tSky')
Blue    Sky

ただし、結果の文字列と比較する前にタブ文字がスペースに変換されるため、doctest の例は失敗します。

>>> import doctest, dedupe
>>> doctest.testmod(dedupe)

与える

Failed example:
    dedupe_whitespace(r"Green           Ground")  #doctest: +REPORT_NDIFF
Differences (ndiff with -expected +actual):
    - 'Green  Ground'
    ?       -
    + 'Green Ground'

テスト結果の比較が適切に実行されるように、doctest ヒアドキュメント文字列でタブ文字をエンコードするにはどうすればよいですか?

4

6 に答える 6

16

docstring のリテラル文字列表記を使用して、これを機能させました。

def join_with_tab(iterable):
    r"""
    >>> join_with_tab(['1', '2'])
    '1\t2'
    """

    return '\t'.join(iterable)

if __name__ == "__main__":
    import doctest
    doctest.testmod()
于 2012-01-13T11:21:16.667 に答える
12

r"""トリックを行ったのは、生のヒアドキュメント文字列表記( )です。

# filename: dedupe.py
import re,doctest
def dedupe_whitespace(s,spacechars='\t '):
    r"""Merge repeated whitespace characters.
    Example:
    >>> dedupe_whitespace('Black\t\tGround')  #doctest: +REPORT_NDIFF
    'Black\tGround'
    """
    for w in spacechars:
        s = re.sub(r"("+w+"+)", w, s)
    return s

if __name__ == "__main__":
    doctest.testmod()
于 2012-01-13T23:15:24.050 に答える
3

TL;DR:バックスラッシュをエスケープします。つまり、変更されていない文字列の\\nor\\tの代わりに\norを使用します。\t

おそらく、docstring を raw にしたくないでしょう。そうすると、Python の文字列エスケープを使用したいものも含めて使用できなくなるからです。

通常のエスケープの使用をサポートするメソッドの場合、バックスラッシュ文字エスケープでバックスラッシュをエスケープするだけです。Python が解釈した後、リテラルのバックスラッシュの後にdoctest解析可能な文字が続きます。

于 2013-08-14T13:38:36.000 に答える
2

これは基本的にYatharhROCKの答えですが、もう少し明確です。生の文字列または二重エスケープを使用できます。しかし、なぜ?

文字列リテラルに有効な Python コードを含める必要があります。これを解釈すると、実行/テストするコードになります。これらは両方とも機能します:

#!/usr/bin/env python

def split_raw(val, sep='\n'):
  r"""Split a string on newlines (by default).

  >>> split_raw('alpha\nbeta\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)


def split_esc(val, sep='\n'):
  """Split a string on newlines (by default).

  >>> split_esc('alpha\\nbeta\\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)

import doctest
doctest.testmod()

生の文字列を使用する効果と二重エスケープ (スラッシュをエスケープする) の効果の両方で、文字列にはスラッシュと n の 2 文字が残ります。このコードは Python インタープリターに渡されます。Python インタープリターは、文字列リテラル内の「改行文字」を意味するために「スラッシュの後に n」を使用します。

好きな方を使用してください。

于 2015-03-07T20:04:52.563 に答える
1

NORMALIZE_WHITESPACEを設定する必要があります。または、代わりに、出力をキャプチャして期待値と比較します。

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> output = dedupe_whitespace(r"Black\t\tGround")  #doctest: +REPORT_NDIFF
    >>> output == 'Black\tGround'
    True
    """

doctestドキュメンテーション セクションからDocstring の例はどのように認識されますか? :

すべてのハード タブ文字は、8 桁のタブ ストップを使用してスペースに展開されます。テストされたコードによって生成された出力のタブは変更されません。サンプル出力のハード タブはすべて展開されているためコード出力にハード タブが含まれている場合、doctest がパスできる唯一の方法は、NORMALIZE_WHITESPACE オプション またはディレクティブが有効である場合です。または、テストの一部として出力を取得し、それを期待値と比較するようにテストを書き直すこともできます。ソース内のタブのこの処理は、試行錯誤の末にたどり着いたものであり、最もエラーが発生しにくい処理方法であることが証明されています。DocTestParserカスタムクラスを作成することで、タブの処理に別のアルゴリズムを使用することができます。

編集:私の間違いです。ドキュメントを逆に理解しました。タブは、渡された文字列引数dedupe_whitespaceと次の行で比較される文字列リテラルの両方で 8 つのスペースに展開されているため、以下がoutput含まれます。

"Black Ground"

と比較されています:

"Black        Ground"

自分で作成したりDocTestParser、タブの代わりに重複排除されたスペースをテストしたりせずに、この制限を克服する方法を見つけることができません。

于 2012-01-12T12:34:47.233 に答える