Set tanda baca lengkap untuk Python (bukan hanya ASCII)

40

Apakah ada daftar atau pustaka yang memiliki semua tanda baca yang biasa kita temui?

Biasanya saya gunakan string.punctuation, tetapi beberapa karakter tanda baca tidak termasuk di dalamnya, misalnya:

>>> "'" in string.punctuation
True
>>> "’" in string.punctuation
False
samuelbrody1249
sumber
Apakah ini menjawab pertanyaan Anda? Cara terbaik untuk menghilangkan tanda baca dari string
serangan udara
9
@airstrike tidak tidak sama sekali.
samuelbrody1249

Jawaban:

54

Anda mungkin lebih baik dengan cek ini:

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

Kategori Unicode P * khusus untuk Tanda baca :

konektor (Pc), tanda hubung (Pd), kutipan awal (Pi), kutipan akhir (Pf), buka (Ps), tutup (Pe), lainnya (Po)

Untuk menyiapkan koleksi lengkap, yang selanjutnya dapat Anda gunakan untuk cek keanggotaan cepat, gunakan pemahaman set:

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

Ekspresi penugasan di sini membutuhkan Python 3.8+, setara dengan versi Python yang lebih lama:

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

Berhati-hatilah karena beberapa karakter lain ada di string.punctuationdalam simbol Unicode kategori . Sangat mudah untuk menambahkan mereka juga jika Anda mau.

wim
sumber
Definisi "tanda baca" yang masuk akal akan mencakup kategori "Simbol" Unicode Sc (mata uang, seperti $), Sk (pengubah, suka ^), Sm (matematika, suka +atau <), dan mungkin So (lainnya, suka ©).
dan04
3
@ dan04 Itulah yang disebutkan para paragraf terakhir dari jawaban. Tentu saja orang lain dapat mengadaptasi kode ini untuk memasukkan / mengecualikan kategori tergantung pada kasus penggunaannya sendiri.
wim
16

Jawaban yang diposting oleh wim benar jika Anda ingin memeriksa apakah suatu karakter adalah karakter tanda baca.

Jika Anda benar-benar membutuhkan daftar semua karakter tanda baca seperti yang disarankan judul pertanyaan Anda, Anda dapat menggunakan yang berikut:

import sys
from unicodedata import category
punctuation_chars =  [chr(i) for i in range(sys.maxunicode) 
                             if category(chr(i)).startswith("P")]
Selcuk
sumber
2

Jawaban oleh wim sangat bagus jika Anda dapat mengubah kode Anda untuk menggunakan suatu fungsi.

Tetapi jika Anda harus menggunakan inoperator (misalnya, Anda memanggil kode perpustakaan), Anda dapat menggunakan mengetik bebek:

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
sumber
1

Itu sepertinya pekerjaan yang bagus untuk ekspresi reguler (regexp):

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

Di sini, regexp mencocokkan semuanya kecuali spasi putih atau karakter kata. Bendera re.UNICODEdigunakan untuk mencocokkan set lengkap karakter Unicode.

Nicolas Martinez
sumber
tidak berfungsi dengan banyak bahasa:>>> text="Den som dræber - fanget" >>> re.sub(r"[^\w\s]", "", str(text), flags=re.UNICODE) 'Den som dr\xc3ber fanget'
samuelbrody1249
1
@ samuelbrody1249 Apa maksudmu itu tidak berhasil? Ini berhasil dalam contoh Anda ( \xc3pelarian adalah hal representasi yang tidak terkait dengan pengupasan tanda baca).
lenz
1
@ lenz \xc3bukan penyandian Unicode yang benar æ; jika Anda mengetik, str(text)Anda dapat mengonfirmasi bahwa itu benar \xc3\xa6. Sebenarnya \xc3sepertinya bukan codepoint yang lengkap.
Federico Poloni
6
Oh begitu. Sepertinya Anda berdua menggunakan Python 2, di mana strstring byte. Anda pasti harus beralih ke Python 3, karena Unicode adalah mimpi buruk di Py2. Bagi saya, str('æ')menunjukkan sebagai 'æ', dan ascii('æ')menunjukkan sebagai '\xe6', yang merupakan titik kode yang benar. b'\xc3\xa6'adalah pengkodean UTF-8 'æ', tetapi ini biasanya tidak sesuai dengan keinginan Anda.
lenz
0

Seperti yang ditunjukkan oleh jawaban lain, cara untuk melakukannya adalah melalui properti / kategori Unicode. Jawaban yang diterima mengakses informasi ini melalui unicodedatamodul perpustakaan standar , tetapi tergantung pada konteks di mana Anda membutuhkan ini, mungkin lebih cepat atau lebih nyaman untuk mengakses informasi properti yang sama ini menggunakan ekspresi reguler.

Namun, remodul perpustakaan standar tidak menyediakan dukungan Unicode yang diperluas. Untuk itu, Anda memerlukan regexmodul , tersedia di 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='’'>

Tinjauan umum yang baik dari semua jenis properti Unicode yang dapat Anda cari menggunakan ekspresi reguler disediakan di sini . Terlepas dari fitur ekspresi ekstra reguler ini, yang didokumentasikan pada beranda PyPI, regexsengaja menyediakan API yang sama re, sehingga Anda diharapkan untuk menggunakan redokumentasi untuk mengetahui cara menggunakan keduanya.

dlukes
sumber