Jawaban:
Dalam Python 3, semua string adalah urutan karakter Unicode. Ada bytes
tipe yang menyimpan byte mentah.
Dalam Python 2, sebuah string dapat berupa tipe str
atau tipe unicode
. Anda dapat mengetahui kode mana yang menggunakan sesuatu seperti ini:
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
Ini tidak membedakan "Unicode atau ASCII"; itu hanya membedakan tipe Python. String Unicode dapat terdiri dari karakter murni dalam rentang ASCII, dan bytestring dapat berisi ASCII, Unicode yang dikodekan, atau bahkan data non-tekstual.
Anda bisa menggunakan type
atau isinstance
.
Dengan Python 2:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
Dalam Python 2, str
hanya urutan byte. Python tidak tahu apa penyandiannya. The unicode
jenis adalah cara yang lebih aman untuk menyimpan teks. Jika Anda ingin lebih memahami ini, saya sarankan http://farmdev.com/talks/unicode/ .
Dengan Python 3:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
Dalam Python 3, str
seperti Python 2 unicode
, dan digunakan untuk menyimpan teks. Apa yang disebut str
dengan Python 2 disebut bytes
dengan Python 3.
Anda bisa menelepon decode
. Jika itu memunculkan eksepsi UnicodeDecodeError, itu tidak valid.
>>> u_umlaut = b'\xc3\x9c' # UTF-8 representation of the letter 'Ü'
>>> u_umlaut.decode('utf-8')
u'\xdc'
>>> u_umlaut.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
unicode(s, "ascii")
sesuatu
str(s, "ascii")
Dalam python 3.x semua string adalah urutan karakter Unicode. dan melakukan isinstance check untuk str (yang berarti string unicode secara default) sudah cukup.
isinstance(x, str)
Sehubungan dengan python 2.x, Kebanyakan orang tampaknya menggunakan pernyataan if yang memiliki dua pemeriksaan. satu untuk str dan satu untuk unicode.
Jika Anda ingin memeriksa apakah Anda memiliki objek 'string-like' semua dengan satu pernyataan, Anda dapat melakukan hal berikut:
isinstance(x, basestring)
isinstance(u"x",basestring)
kembali True
.
Unicode bukan pengodean - mengutip Kumar McMillan:
Jika ASCII, UTF-8, dan string byte lainnya adalah "teks" ...
... maka Unicode adalah "text-ness";
itu adalah bentuk abstrak dari teks
Telah membaca tentang McMillan's Unicode In Python, bicara Sepenuhnya Demystified dari PyCon 2008, itu menjelaskan banyak hal lebih baik daripada sebagian besar jawaban terkait pada Stack Overflow.
Jika kebutuhan kode Anda agar kompatibel dengan kedua Python 2 dan Python 3, Anda tidak bisa langsung menggunakan hal-hal seperti isinstance(s,bytes)
atau isinstance(s,unicode)
tanpa membungkus mereka baik mencoba / kecuali atau tes versi python, karena bytes
tidak terdefinisi dengan Python 2 dan unicode
tidak terdefinisi di Python 3 .
Ada beberapa solusi buruk. Yang sangat jelek adalah membandingkan nama tipe, bukan membandingkan tipe itu sendiri. Ini sebuah contoh:
# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
# only possible in Python 3
s = s.decode('ascii') # or s = str(s)[2:-1]
elif str(type(s)) == "<type 'unicode'>":
# only possible in Python 2
s = str(s)
Solusi yang bisa dibilang sedikit kurang jelek adalah memeriksa nomor versi Python, misalnya:
if sys.version_info >= (3,0,0):
# for Python 3
if isinstance(s, bytes):
s = s.decode('ascii') # or s = str(s)[2:-1]
else:
# for Python 2
if isinstance(s, unicode):
s = str(s)
Keduanya unpythonic, dan sebagian besar waktu mungkin ada cara yang lebih baik.
six
, dan uji terhadap six.binary_type
dansix.text_type
menggunakan:
import six
if isinstance(obj, six.text_type)
di dalam enam perpustakaan direpresentasikan sebagai:
if PY3:
string_types = str,
else:
string_types = basestring,
if isinstance(obj, six.text_type)
. Tapi ya ini adalah jawaban yang benar.
Perhatikan bahwa pada Python 3, tidak adil untuk mengatakan:
str
s adalah UTFx untuk x (mis. UTF8)
str
Ini adalah Unicode
str
s adalah koleksi karakter Unicode yang dipesan
str
Jenis Python adalah (biasanya) urutan titik kode Unicode, beberapa di antaranya memetakan karakter.
Bahkan di Python 3, tidak semudah menjawab pertanyaan ini seperti yang Anda bayangkan.
Cara yang jelas untuk menguji string yang kompatibel dengan ASCII adalah dengan mencoba penyandian:
"Hello there!".encode("ascii")
#>>> b'Hello there!'
"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>> File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)
Kesalahan membedakan kasus.
Di Python 3, bahkan ada beberapa string yang berisi poin kode Unicode yang tidak valid:
"Hello there!".encode("utf8")
#>>> b'Hello there!'
"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>> File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed
Metode yang sama untuk membedakan mereka digunakan.
Ini dapat membantu orang lain, saya memulai pengujian untuk tipe string dari variabel s, tetapi untuk aplikasi saya, lebih masuk akal untuk mengembalikan s sebagai utf-8. Proses memanggil return_utf, kemudian tahu apa yang ia hadapi dan dapat menangani string dengan tepat. Kode ini tidak asli, tetapi saya bermaksud untuk menjadi agnostik versi Python tanpa tes versi atau mengimpor enam. Berikan komentar dengan penyempurnaan kode contoh di bawah ini untuk membantu orang lain.
def return_utf(s):
if isinstance(s, str):
return s.encode('utf-8')
if isinstance(s, (int, float, complex)):
return str(s).encode('utf-8')
try:
return s.encode('utf-8')
except TypeError:
try:
return str(s).encode('utf-8')
except AttributeError:
return s
except AttributeError:
return s
return s # assume it was already utf-8
Anda dapat menggunakan Universal Encoding Detector , tetapi ketahuilah bahwa itu hanya akan memberi Anda tebakan terbaik, bukan pengkodean yang sebenarnya, karena tidak mungkin untuk mengetahui pengkodean string "abc" misalnya. Anda perlu mendapatkan informasi penyandian di tempat lain, mis. Protokol HTTP menggunakan header Tipe-Konten untuk itu.
Untuk kompatibilitas py2 / py3 cukup gunakan
import six
if isinstance(obj, six.text_type)
Salah satu pendekatan sederhana adalah untuk memeriksa apakah unicode
fungsi builtin. Jika demikian, Anda menggunakan Python 2 dan string Anda akan menjadi string. Untuk memastikan semuanya dalam unicode
satu dapat dilakukan:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)