คำตอบ:
ใน Python 3 สตริงทั้งหมดเป็นลำดับของอักขระ Unicode มีbytes
ชนิดที่เก็บไบต์ดิบ
ในหลาม 2 สตริงอาจจะเป็นประเภทหรือชนิดstr
unicode
คุณสามารถบอกได้ว่าใช้รหัสอะไรเช่นนี้:
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
สิ่งนี้ไม่แยกความแตกต่าง "Unicode หรือ ASCII"; มันแยกประเภท Python เท่านั้น สตริง Unicode อาจประกอบด้วยอักขระล้วน ๆ ในช่วง ASCII และการทดสอบอาจมี ASCII, Unicode ที่เข้ารหัสหรือแม้แต่ข้อมูลที่ไม่ใช่ข้อความ
คุณสามารถใช้หรือtype
isinstance
ใน Python 2:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
ใน Python 2 str
เป็นเพียงลำดับของไบต์ Python ไม่ทราบว่าการเข้ารหัสนั้นคืออะไร unicode
ประเภทเป็นวิธีที่ปลอดภัยในการเก็บข้อความ หากคุณต้องการที่จะเข้าใจมากขึ้นนี้ผมขอแนะนำให้http://farmdev.com/talks/unicode/
ใน Python 3:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
ใน Python 3 str
เหมือนกับ Python 2 unicode
และใช้เพื่อเก็บข้อความ สิ่งที่ถูกเรียกstr
ใน Python 2 นั้นถูกเรียกbytes
ใน Python 3
decode
คุณสามารถโทรหา ถ้ามันทำให้เกิดข้อยกเว้น UnicodeDecodeError มันไม่ถูกต้อง
>>> 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")
หรืออะไรบางอย่าง
str(s, "ascii")
ใน python 3.x สตริงทั้งหมดเป็นลำดับของอักขระ Unicode และทำการตรวจสอบ isinstance เพื่อหา str (ซึ่งหมายความว่ายูนิโค้ดสตริงโดยค่าเริ่มต้น) ควรพอเพียง
isinstance(x, str)
สำหรับ python 2.x คนส่วนใหญ่ดูเหมือนจะใช้คำสั่ง if ที่มีการตรวจสอบสองครั้ง หนึ่งสำหรับ str และอีกหนึ่งสำหรับ Unicode
หากคุณต้องการตรวจสอบว่าคุณมีวัตถุ 'เหมือนสตริง' ทั้งหมดด้วยคำสั่งเดียวคุณสามารถทำสิ่งต่อไปนี้:
isinstance(x, basestring)
isinstance(u"x",basestring)
True
Unicode ไม่ใช่การเข้ารหัส - เพื่ออ้างอิง Kumar McMillan:
ถ้า ASCII, UTF-8 และสตริงไบต์อื่นคือ "text" ...
... ดังนั้น Unicode คือ "text-ness";
มันเป็นรูปแบบนามธรรมของข้อความ
อ่านUnicodeของ McMillan ใน Python การพูดคุยที่ไม่เข้าใจอย่างสมบูรณ์จาก PyCon 2008 มันอธิบายสิ่งต่าง ๆ ได้ดีกว่าคำตอบที่เกี่ยวข้องส่วนใหญ่ใน Stack Overflow
หากรหัสของคุณต้องเข้ากันได้กับทั้ง Python 2 และ Python 3 คุณไม่สามารถใช้สิ่งต่าง ๆ เช่นisinstance(s,bytes)
หรือisinstance(s,unicode)
ไม่ใส่ในการลอง / ยกเว้นหรือการทดสอบเวอร์ชันของ Python เนื่องจากbytes
ไม่ได้กำหนดไว้ใน Python 2 และunicode
ไม่ได้กำหนดไว้ใน Python 3 .
มีวิธีแก้ปัญหาที่น่าเกลียดอยู่บ้าง สิ่งที่น่าเกลียดอย่างยิ่งคือการเปรียบเทียบชื่อของประเภทแทนที่จะเปรียบเทียบชนิดของมันเอง นี่คือตัวอย่าง:
# 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)
วิธีแก้ปัญหาที่น่าเกลียดน้อยกว่าเล็กน้อยคือการตรวจสอบหมายเลข Python เช่น:
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)
สิ่งเหล่านี้เป็นทั้งเสียงที่ไม่ไพเราะและส่วนใหญ่อาจมีวิธีที่ดีกว่า
six
และทดสอบกับsix.binary_type
และsix.text_type
ใช้:
import six
if isinstance(obj, six.text_type)
ภายในห้องสมุดทั้งหกจะแสดงเป็น:
if PY3:
string_types = str,
else:
string_types = basestring,
if isinstance(obj, six.text_type)
มันควรจะเป็น แต่ใช่นี้เป็นคำตอบที่ถูกต้อง
โปรดทราบว่าใน Python 3 มันไม่ยุติธรรมเลยที่จะพูดอะไร:
str
s คือ UTFx สำหรับ x ใด ๆ (เช่น. UTF8)
str
s คือ Unicode
str
s คือชุดของอักขระ Unicode ที่เรียงลำดับแล้ว
str
ชนิดของ Python คือ (โดยปกติ) ลำดับของจุดโค้ด Unicode ซึ่งบางส่วนจะจับคู่กับอักขระ
แม้แต่ใน Python 3 มันไม่ง่ายเลยที่จะตอบคำถามนี้อย่างที่คุณคิด
วิธีที่ชัดเจนในการทดสอบสตริงที่เข้ากันได้กับ ASCII คือการเข้ารหัสแบบพยายาม:
"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)
ข้อผิดพลาดแยกความแตกต่างกรณี
ใน Python 3 มีบางสตริงที่มีจุดโค้ด Unicode ที่ไม่ถูกต้อง:
"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
ใช้วิธีการเดียวกันเพื่อแยกแยะความแตกต่าง
สิ่งนี้อาจช่วยคนอื่นฉันเริ่มทำการทดสอบชนิดสตริงของตัวแปร s แต่สำหรับแอปพลิเคชันของฉันมันสมเหตุสมผลกว่าที่จะคืนค่า s เป็น utf-8 กระบวนการเรียก return_utf จากนั้นรู้ว่ามันเกี่ยวข้องกับอะไรและสามารถจัดการกับสตริงได้อย่างเหมาะสม รหัสไม่ใช่ของบริสุทธิ์ แต่ฉันตั้งใจให้เป็นรุ่น Python ไม่เชื่อเรื่องพระเจ้าโดยไม่ต้องทดสอบรุ่นหรือนำเข้าหก โปรดแสดงความคิดเห็นพร้อมการปรับปรุงโค้ดตัวอย่างด้านล่างเพื่อช่วยเหลือผู้อื่น
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
คุณสามารถใช้เครื่องตรวจจับการเข้ารหัสสากลแต่โปรดทราบว่าเครื่องจะให้การคาดเดาที่ดีที่สุดไม่ใช่การเข้ารหัสที่แท้จริงเพราะมันเป็นไปไม่ได้ที่จะรู้การเข้ารหัสของสตริง "abc" คุณจะต้องได้รับข้อมูลการเข้ารหัสที่อื่นเช่นโปรโตคอล HTTP ใช้ส่วนหัวของประเภทเนื้อหาสำหรับสิ่งนั้น
สำหรับการใช้งานร่วมกันได้ของ py2 / py3
import six
if isinstance(obj, six.text_type)
วิธีการง่าย ๆ อย่างหนึ่งคือการตรวจสอบว่าunicode
เป็นฟังก์ชันในตัวหรือไม่ ถ้าเป็นเช่นนั้นคุณอยู่ใน Python 2 และสตริงของคุณจะเป็นสตริง เพื่อให้มั่นใจว่าทุกอย่างในที่unicode
เดียวทำได้:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)