Проверьте, является ли символ Unicode способом, совместимым с Python 2 и 3 - PullRequest
0 голосов
/ 14 сентября 2018

РЕДАКТИРОВАТЬ : уточнение разрешенного набора символов на основе комментариев

Допустимые символы из набора символов ASCII: a-z, A-Z, 0-9, -, _, ., /. Любой другой символ из набора ASCII не должен быть разрешен.

Также допускаются символы Unicode, кроме запрещенного набора ASCII, определенного выше.

Конец редактирования

Я обрабатываю некоторые текстовые данные, где единственными допустимыми символами ASCII являются a-z, A-Z, 0-9 и -, _, ., /. Помимо этих символов Unicode также допускается. Мне нужно убедиться, что входящие данные содержат только этот набор символов.

Проверка допустимых символов ASCII проста:

from string import ascii_letters, digits
VALID_CHARSET= set(ascii_letters + digits + "-_./")

def is_valid_string(string):
    for c in string:
        if c not in VALID_CHARSET:
            return False
    return True

Но мне интересно, как можно разрешить символы юникода помимо вышеперечисленного. Я думаю, в Python-2.7 я мог бы добавить проверку следующим образом:

if isinstance(c, unicode)
    return True
if c not in VALID_CHARSET:
    return False

Но строки в Python-3 по умолчанию являются Unicode, и отдельного типа unicode не существует, поэтому это не сработает. Любой более чистый способ сделать это, который работает в обеих версиях Python?

1 Ответ

0 голосов
/ 15 сентября 2018

Когда я читаю вопрос, вы хотите разрешить любой не-ASCII символ, а также символы ASCII в белом списке. Поскольку создание набора из всех допустимых символов нецелесообразно (в нем должно быть более миллиона записей), самое простое решение - создать набор недопустимых символов и убедиться, что в ваших строках нет ни одного из них:

VALID_CHARSET = frozenset(ascii_letters + digits + "-_./")
INVALID_CHARSET = frozenset(map(chr, range(128))) - VALID_CHARSET

Как только вы это получите, is_valid_string становится тривиальным:

def is_valid_string(string):
    return INVALID_CHARSET.isdisjoint(string)

Если вам так хочется, вы даже можете вообще избежать определения функции уровня Python, сэкономив немного накладных расходов (за счет невозможности определить вашу собственную строку документации), просто создав псевдоним для привязки isdisjoint метод:

is_valid_string = INVALID_CHARSET.isdisjoint

Вы не получите быстрее, чем это; set / frozenset метод isdisjoint переносит всю работу на уровень C (без обработки байт-кода на символ), короткое замыкание (как только появляется недопустимый символ, оно немедленно возвращается) и выполняет каждый поиск в ~ O(1) (поэтому проверка строки равна O(n) по длине строки).

Если вас не интересует проверка , а, скорее, вы хотите удалить недопустимые символы, вы можете использовать str.translate / unicode.translate для массового удаления недопустимых символов, но с учетом API отличается между типами (Py3 str и Py2 unicode используют одну форму, Py3 bytes и Py2 str другую), вам придется пойти на некоторые проблемы, чтобы он работал на Py2 и Py3 на та же база кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...