ฟังก์ชัน maketrans() ของ Python 2 ใช้ไม่ได้กับ Unicode: อาร์กิวเมนต์จะมีความยาวต่างกันเมื่อเป็นจริง

[หลาม 2] SUB = string.maketrans("0123456789","₀₁₂₃₄₅₆₇₈₉")

รหัสนี้ก่อให้เกิดข้อผิดพลาด:

ValueError: maketrans arguments must have same length

ฉันไม่แน่ใจว่าเหตุใดจึงเกิดขึ้นเนื่องจากสตริงมีความยาวเท่ากัน ความคิดเดียวของฉันคือความยาวของข้อความตัวห้อยแตกต่างจากอักขระขนาดมาตรฐาน แต่ฉันไม่รู้ว่าจะแก้ไขอย่างไร


person Aaron    schedule 07.05.2015    source แหล่งที่มา
comment
ทำงานได้ดีใน Python 3 (ซึ่งรองรับ Unicode ได้ดีกว่ามากอยู่แล้ว) นั่นเป็นตัวเลือกสำหรับคุณหรือไม่   -  person Stefan Pochmann    schedule 07.05.2015
comment
ขณะนี้ฉันใช้ python 2.7 แต่ฉันจะดู Python 3 อย่างแน่นอน   -  person Aaron    schedule 07.05.2015
comment
รหัส Python 3 นั้นมาจากคำตอบที่ชัดเจนของ @ZeroPiraeus ต่อ การพิมพ์ตัวห้อยใน python   -  person smci    schedule 10.09.2018


คำตอบ (1)


ไม่ อาร์กิวเมนต์มีความยาวไม่เท่ากัน:

>>> len("0123456789")
10
>>> len("₀₁₂₃₄₅₆₇₈₉")
30

คุณกำลังพยายามส่งข้อมูลที่เข้ารหัส; ฉันใช้ UTF-8 ที่นี่ โดยแต่ละหลักจะถูกเข้ารหัสเป็น 3 ไบต์

คุณไม่สามารถใช้ str.translate() เพื่อจับคู่ไบต์ ASCII กับลำดับไบต์ UTF-8 ถอดรหัสสตริงของคุณเป็น unicode และใช้วิธี unicode.translate() ที่แตกต่างกันเล็กน้อย ต้องใช้ พจนานุกรม แทน:

nummap = {ord(c): ord(t) for c, t in zip(u"0123456789", u"₀₁₂₃₄₅₆₇₈₉")}

สิ่งนี้จะสร้างการแมปพจนานุกรมจุดรหัส Unicode (จำนวนเต็ม) ซึ่งคุณสามารถใช้กับสตริง Unicode ได้:

>>> nummap = {ord(c): ord(t) for c, t in zip(u"0123456789", u"₀₁₂₃₄₅₆₇₈₉")}
>>> u'99 bottles of beer on the wall'.translate(nummap)
u'\u2089\u2089 bottles of beer on the wall'
>>> print u'99 bottles of beer on the wall'.translate(nummap)
₉₉ bottles of beer on the wall

จากนั้นคุณสามารถเข้ารหัสเอาต์พุตเป็น UTF-8 อีกครั้งได้หากต้องการ

จากเอกสารประกอบวิธีการ:

สำหรับออบเจ็กต์ Unicode เมธอด translate() จะไม่ยอมรับอาร์กิวเมนต์ deletechars ที่เป็นทางเลือก แต่จะส่งคืนสำเนาของ s โดยที่อักขระทั้งหมดได้รับการแมปผ่านตารางการแปลที่กำหนด ซึ่งจะต้องเป็นการแมปลำดับ Unicode กับลำดับ Unicode, สตริง Unicode หรือ None อักขระที่ไม่ได้แมปจะถูกปล่อยทิ้งไว้โดยไม่มีใครแตะต้อง อักขระที่แมปกับ None จะถูกลบ

person Martijn Pieters    schedule 07.05.2015
comment
มีวิธีอื่นในการรับอักขระตัวห้อยใน python หรือไม่? หรือแม้แต่วิธีที่จะเอาชนะความแตกต่างที่ยาวขนาดนี้ - person Aaron; 07.05.2015
comment
แอรอน: นี่จะไม่ใช่ข้อจำกัดของ Python ... แต่เป็นนัยของความแตกต่างระหว่าง ASCII และ Unicode ไม่มีอักขระตัวห้อยใน ASCII ผลกระทบของการใช้อักขระ Unicode ก็คือ Python ไม่สามารถปฏิบัติต่ออักขระดังกล่าวราวกับว่าเป็น ASCII --- ความพยายามใดๆ ที่จะทำเช่นนั้นอาจได้ผลในบางกรณี แต่จะใช้งานไม่ได้สำหรับอักขระอื่นๆ - person Jim Dennis; 07.05.2015
comment
@Martijn คุณได้ 30 มาจากไหน? ฉันได้รับอักขระ 10 ตัวหรืออักขระที่ไม่รองรับในการป้อนข้อมูล ขึ้นอยู่กับว่าฉันลองใช้ที่ไหน - person Stefan Pochmann; 07.05.2015
comment
@StefanPochmann: การใช้ล่ามแบบโต้ตอบในเทอร์มินัลที่กำหนดค่าสำหรับการใช้งาน UTF-8 - person Martijn Pieters; 07.05.2015
comment
เฉพาะใน Python 2 เท่านั้น ความยาวคือ 30 ใน Python 2 และ 10 ใน Python 3 รหัสของ OP ทำงานได้ดีใน Python 3 - person smci; 10.09.2018
comment
@smci อย่างแน่นอน; คุณจะเห็นเฉพาะข้อผิดพลาดนี้ใน Python 2 เนื่องจากเป็นสตริงไบต์ นั่นเป็นสาเหตุที่คำถามถูกแท็กด้วยแท็ก python-2.x - person Martijn Pieters; 10.09.2018