Convertir la representación Unicode de un número a una cadena ASCII

He estado buscando una forma sencilla de convertir un número de una cadena Unicode a una cadena ASCII en Python. Por ejemplo, la entrada:

input = u'\u0663\u0669\u0668\u066b\u0664\u0667' 

Debe rendir '398.47' .

Comencé con:

 NUMERALS_TRANSLATION_TABLE = {0x660:ord("0"), 0x661:ord("1"), 0x662:ord("2"), 0x663:ord("3"), 0x664:ord("4"), 0x665:ord("5"), 0x666:ord("6"), 0x667:ord("7"), 0x668:ord("8"), 0x669:ord("9"), 0x66b:ord(".")} input.translate(NUMERALS_TRANSLATION_TABLE) 

Esta solución funcionó, pero quiero poder admitir todos los caracteres relacionados con números en Unicode, y no solo en árabe. Puedo traducir los dígitos repasando la cadena Unicode y ejecutando unicodedata.digit(input[i]) en cada carácter. No me gusta esta solución, porque no resuelve '\u066b' o '\u2013' . Podría resolverlos utilizando la translate como alternativa alternativa, pero no estoy seguro de si hay otros personajes similares de los que no tengo conocimiento actualmente, por lo que estoy tratando de buscar una solución mejor y más elegante.

Cualquier sugerencia sería muy apreciada.

El uso de unicodedata.digit() para buscar los valores de dígitos para puntos de código “numéricos” es el método correcto:

 >>> import unicodedata >>> unicodedata.digit(u'\u0663') 3 

Esto utiliza la información estándar de Unicode para buscar valores numéricos para un punto de código determinado.

Puedes construir una tabla de traducción usando str.isdigit() para probar los dígitos; Esto es cierto para todos los puntos de código para los cuales el estándar define un valor numérico. Para los puntos decimales, puede buscar DECIMAL SEPARATOR en el nombre; El estándar no realiza un seguimiento de estos por separado por ninguna otra métrica:

 NUMERALS_TRANSLATION_TABLE = { i: unicode(unicodedata.digit(unichr(i))) for i in range(2 ** 16) if unichr(i).isdigit()} NUMERALS_TRANSLATION_TABLE.update( (i, u'.') for i in range(2 ** 16) if 'DECIMAL SEPARATOR' in unicodedata.name(unichr(i), '')) 

Eso produce una tabla de 447 entradas, que incluye 2 puntos decimales en U + 066b SEPARADOR DECIMAL ÁRABE y U + 2396 SÍMBOLO DE CLAVE DEL SEPARADOR DECIMAL ; este último es en realidad solo un símbolo inventado para colocar la tecla separadora decimal en un teclado numérico en el que un fabricante no desea comprometerse a imprimir un , o . separador decimal en esa clave.

Manifestación:

 >>> import unicodedata >>> NUMERALS_TRANSLATION_TABLE = { ... i: unicode(unicodedata.digit(unichr(i))) ... for i in range(2 ** 16) if unichr(i).isdigit()} >>> NUMERALS_TRANSLATION_TABLE.update( ... (i, u'.') for i in range(2 ** 16) ... if 'DECIMAL SEPARATOR' in unicodedata.name(unichr(i), '')) >>> input = u'\u0663\u0669\u0668\u066b\u0664\u0667' >>> input.translate(NUMERALS_TRANSLATION_TABLE) '398.47' 
 >>> from unidecode import unidecode >>> unidecode(u'\u0663\u0669\u0668\u066b\u0664\u0667') '398.47'