Полный набор знаков препинания для Python (не только ASCII)

40

Есть ли список или библиотека, в которой есть все знаки препинания, с которыми мы обычно сталкиваемся?

Обычно я использую string.punctuation, но некоторые знаки препинания не включены в него, например:

>>> "'" in string.punctuation
True
>>> "’" in string.punctuation
False
samuelbrody1249
источник
Отвечает ли это на ваш вопрос? Лучший способ снять пунктуацию со строки
авиаудар
9
@airstrike нет, совсем нет.
samuelbrody1249

Ответы:

54

Вы могли бы сделать лучше с этой проверкой:

>>> import unicodedata
>>> unicodedata.category("'").startswith("P")
True
>>> unicodedata.category("’").startswith("P")
True

Unicode категории P * специально для пунктуации :

соединитель (Pc), тире (Pd), начальная кавычка (Pi), окончательная кавычка (Pf), открытый (Ps), закрытый (Pe), другой (Po)

Чтобы подготовить исчерпывающую коллекцию, которую вы впоследствии сможете использовать для быстрой проверки членства, используйте набор пониманий:

>>> import sys
>>> from unicodedata import category
>>> codepoints = range(sys.maxunicode + 1)
>>> punctuation = {c for i in codepoints if category(c := chr(i)).startswith("P")}
>>> "'" in punctuation
True
>>> "’" in punctuation
True

Выражение присваивания здесь требует Python 3.8+, эквивалент для более старых версий Python:

chrs = (chr(i) for i in range(sys.maxunicode + 1))
punctuation = set(c for c in chrs if category(c).startswith("P"))

Помните, что некоторые другие символы в string.punctuationдействительности находятся в категории символов Unicode . Это легко добавить, если вы хотите.

Wim
источник
Разумное определение «пунктуации» будет включать в себя Unicode-категории «Символ» Sc (валюта, как $), Sk (модификатор, как ^), Sm (математика, как +или <) и, возможно, So (другое, как ©).
Ден04
3
@ dan04 Об этом говорится в последнем абзаце ответа. Конечно, другие могут адаптировать этот код для включения / исключения категорий в зависимости от их собственного варианта использования.
Вим
16

Ответ от wim верен, если вы хотите проверить, является ли символ знаком пунктуации.

Если вам действительно нужен список всех знаков препинания, как подсказывает заголовок вашего вопроса, вы можете использовать следующее:

import sys
from unicodedata import category
punctuation_chars =  [chr(i) for i in range(sys.maxunicode) 
                             if category(chr(i)).startswith("P")]
Сельчук
источник
2

Ответ от wim хорош, если вы можете изменить свой код для использования функции.

Но если вам нужно использовать inоператор (например, вы вызываете код библиотеки), вы можете использовать утку:

import unicodedata
class DuckType:
    def __contains__(self,s):
        return unicodedata.category(s).startswith("P")
punct=DuckType()
#print("'" in punct,'"' in punct,"a" in punct)
xkcdjerry
источник
1

Это выглядит как хорошая работа для регулярного выражения (регулярное выражение):

    import re
    text = re.sub(r"[^\w\s]", "", str(text), flags=re.UNICODE)

Здесь регулярное выражение соответствует всем, кроме пробелов или символов слова. Флаг re.UNICODEиспользуется для сопоставления с полным набором символов Юникода.

Николас Мартинес
источник
не работает со многими языками:>>> text="Den som dræber - fanget" >>> re.sub(r"[^\w\s]", "", str(text), flags=re.UNICODE) 'Den som dr\xc3ber fanget'
samuelbrody1249
1
@ samuelbrody1249 Что вы имеете в виду, что это не работает? Это работает в вашем примере ( \xc3побег - это репрезентация, не связанная со снятием знаков препинания).
Lenz
1
@lenz \xc3не является правильной кодировкой Unicode æ; если вы напечатаете, str(text)вы можете подтвердить, что это так \xc3\xa6. На самом деле \xc3, похоже, не полная кодовая точка.
Федерико Полони
6
А ну понятно. Кажется, вы оба используете Python 2, где strесть строка байтов. Вам определенно следует переключиться на Python 3, потому что Unicode - это кошмар в Py2. Для меня str('æ')показывает как 'æ', и ascii('æ')показывает как '\xe6', что является правильной кодовой точкой. b'\xc3\xa6'кодировка UTF-8 'æ', но обычно это не то, с чем вы хотите работать.
Ленц
0

Как указывалось в других ответах, способ сделать это - через свойства / категории Unicode. Принятый ответ обращается к этой информации через стандартный библиотечный unicodedataмодуль, но в зависимости от контекста, где это необходимо, может быть быстрее или удобнее получить доступ к этой же информации о свойствах с помощью регулярных выражений.

Однако стандартный reмодуль библиотеки не обеспечивает расширенной поддержки Unicode. Для этого вам нужен regexмодуль , доступный в PyPI ( pip install regex):

>>> import regex as re
>>> re.match("\p{Punctuation}", "'")
<regex.Match object; span=(0, 1), match="'">
>>> re.match("\p{Punctuation}", "’")
<regex.Match object; span=(0, 1), match='’'>

Хороший обзор всех различных типов свойств Unicode, которые вы можете искать с помощью регулярных выражений, представлен здесь . Помимо этих дополнительных функций регулярных выражений, которые задокументированы на его домашней странице PyPI, regexнамеренно предоставляет тот же API re, что и вы, вероятно, будете использовать reдокументацию, чтобы выяснить, как использовать любой из них.

dlukes
источник