una tipos separar por palabra letras imprimir funcion eliminar comparar caracteres caracter cadenas cadena python string special-characters quotes doctest

tipos - string en python



¿Cómo puedo incluir caracteres especiales(tabulación, nueva línea) en una cadena de resultados de doctest de python? (6)

Conseguí que funcionara al escapar del carácter de tabulación en la cadena esperada:

>>> function_that_returns_tabbed_text() ''//t//t//tsometext//t//t''

en lugar de

>>> function_that_returns_tabbed_text() /t/t/tsometext/t/t

Dado el siguiente script de 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

La función funciona según lo previsto en el intérprete de python:

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

Sin embargo, el ejemplo de doctest falla porque los caracteres de la pestaña se convierten en espacios antes de la comparación con la cadena de resultados:

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

da

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

¿Cómo puedo codificar los caracteres de tabulación en una cadena heredoc doctest para que la comparación de los resultados de la prueba se realice correctamente?


Debe establecer el NORMALIZE_WHITESPACE . O, alternativamente, capture la salida y compárela con el valor esperado:

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 """

De la sección de documentación de doctest ¿Cómo se reconocen los ejemplos de Docstring? :

Todos los caracteres de las pestañas duras se expanden a espacios, utilizando tabulaciones de 8 columnas. Las pestañas en la salida generada por el código probado no se modifican. Debido a que todas las pestañas duras en la salida de muestra están expandidas, esto significa que si la salida del código incluye pestañas duras, la única manera en que puede pasar el doctest es si la opción o directiva NORMALIZE_WHITESPACE está vigente. Alternativamente, la prueba se puede reescribir para capturar la salida y compararla con un valor esperado como parte de la prueba. Este manejo de las pestañas en la fuente se realizó mediante prueba y error, y ha demostrado ser la forma menos propensa a manejarlas. Es posible usar un algoritmo diferente para manejar las pestañas escribiendo una clase personalizada DocTestParser .

Edit: Mi error, entendí los documentos al revés. Las pestañas se expanden a 8 espacios tanto en el argumento de cadena que se pasa a dedupe_whitespace como en el literal de cadena que se compara en la siguiente línea, por lo que la output contiene:

"Black Ground"

y se está comparando con:

"Black Ground"

No puedo encontrar una manera de superar esta limitación sin escribir su propio DocTestParser o probar los espacios deduplicados en lugar de pestañas.


Es la notación de cadena heredoc cruda ( r""" ) que hizo el truco:

# 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()


Esta es básicamente la respuesta de YatharhROCK, pero un poco más explícita. Puede utilizar cadenas en bruto o doble de escape. ¿Pero por qué?

Necesita que la cadena literal contenga un código de Python válido que, cuando se interpreta, es el código que desea ejecutar / probar. Estos dos funcionan:

#!/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()

El efecto de usar cadenas en bruto y el efecto de doble escape (escape de la barra) ambos deja en la cadena dos caracteres, la barra y la n. Este código se pasa al intérprete de Python, que toma "barra diagonal luego n" para significar "carácter de nueva línea" dentro de una cadena literal.

Usa lo que prefieras.


He conseguido que esto funcione con la notación de cadena literal para la cadena de documentos:

def join_with_tab(iterable): r""" >>> join_with_tab([''1'', ''2'']) ''1/t2'' """ return ''/t''.join(iterable) if __name__ == "__main__": import doctest doctest.testmod()


TL; DR: Escape la barra diagonal inversa, es decir, use //n o //t lugar de /n o /t en sus cadenas de otro modo no modificadas;

Es probable que no desee que sus cadenas de documentos se vuelvan sin formato, ya que entonces no podrá utilizar ningún escape de cadena de Python, incluidos aquellos que podría desear.

Para un método que admite el uso de escapes normales, simplemente escapa la barra diagonal inversa en el escape de caracteres de barra invertida, por lo que, después de que Python lo interprete, deja una barra invertida literal seguida del carácter que doctest puede analizar.