لماذا يستخدم unicode() str() على الكائن الخاص بي فقط دون تقديم أي تشفير؟

StackOverflow https://stackoverflow.com/questions/106630

  •  01-07-2019
  •  | 
  •  

سؤال

أبدأ بإنشاء متغير سلسلة مع البعض غير أسكي أوتف-8 البيانات المشفرة عليه:

>>> text = 'á'
>>> text
'\xc3\xa1'
>>> text.decode('utf-8')
u'\xe1'

استخدام unicode() عليه يثير الأخطاء..

>>> unicode(text)
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(text, 'utf-8')
u'\xe1'
>>> unicode(text, 'utf-8') == text.decode('utf-8')
True

الآن إذا كان لدي فصل دراسي يقوم بإرجاع هذا النص في ملف __str__() طريقة:

>>> class ReturnsEncoded(object):
...     def __str__(self):
...         return text
... 
>>> r = ReturnsEncoded()
>>> str(r)
'\xc3\xa1'

unicode(r) يبدو للاستخدام str() عليه، لأنه يثير نفس الخطأ كما unicode(text) فوق:

>>> unicode(r)
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(r, 'utf-8') لن تحاول حتى:

>>> unicode(r, 'utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found

لماذا؟لماذا هذا السلوك غير المتسق؟هل هذه حقيب؟هل المقصود؟محرجا جدا.

هل كانت مفيدة؟

المحلول

يبدو السلوك مربكًا ولكنه متعمد.أقوم هنا بإعادة إنتاج كامل وثائق Unicode من ملف وثائق وظائف بايثون المضمنة (للإصدار 2.5.2، وأنا أكتب هذا):

يونيكود([كائن[، ترميز [، أخطاء]]])

قم بإرجاع إصدار سلسلة Unicode للكائن باستخدام أحد الأوضاع التالية:

إذا تم إعطاء الترميز و/أو الأخطاء ، فسيقوم Unicode () بفك تشفير الكائن الذي يمكن أن يكون إما سلسلة 8 بت أو مخزن مؤقت للحرف باستخدام الترميز للتشفير.المعلمة الترميز هي سلسلة تعطي اسم الترميز ؛إذا لم يكن الترميز معروفًا ، يتم رفع LookeProror.يتم التعامل مع الخطأ وفقًا للأخطاء ؛هذا يحدد معالجة الأحرف غير صالحة في ترميز الإدخال.إذا كانت الأخطاء "صارمة" (الافتراضي) ، يتم رفع القيمة على الأخطاء ، في حين أن قيمة "تجاهل" تسبب في تجاهل الأخطاء بصمت ، وتسبب قيمة "استبدال" حرف استبدال Unicode الرسمي ، U+FFFD ، لاستخدامها لاستبدال أحرف الإدخال التي لا يمكن فك تشفيرها.أنظر أيضاً برامج الترميز وحدة.

إذا لم يتم تقديم معلمات اختيارية ، فسيحاكي Unicode () سلوك STR () باستثناء أنه يعيد سلاسل Unicode بدلاً من سلاسل 8 بت.بتعبير أدق ، إذا كان الكائن عبارة عن سلسلة أو فئة فرعية Unicode ، فسيتم إرجاع سلسلة Unicode دون تطبيق أي فك تشفير إضافي.

بالنسبة للكائنات التي توفر طريقة __unicode __ () ، فسوف تسمي هذه الطريقة بدون وسيط لإنشاء سلسلة Unicode.بالنسبة لجميع الكائنات الأخرى ، يتم طلب إصدار السلسلة المكونة من 8 بت ثم تحويله إلى سلسلة Unicode باستخدام برنامج الترميز للترميز الافتراضي في الوضع "الصارم".

الجديد في الإصدار 2.0.تم التغيير في الإصدار 2.2:تمت إضافة دعم لـ __unicode__().

لذلك، عند الاتصال unicode(r, 'utf-8'), ، فهو يتطلب سلسلة مكونة من 8 بت أو مخزن مؤقت للأحرف كوسيطة أولى، لذا فهو يفرض الكائن الخاص بك باستخدام __str__() الطريقة، ومحاولات فك ذلك باستخدام utf-8 برنامج الترميز.بدون ال utf-8, ، ال unicode() تبحث الوظيفة عن a لـ a __unicode__() الأسلوب على الكائن الخاص بك، وعدم العثور عليه، يستدعي __str__() الطريقة، كما اقترحت، تحاول استخدام برنامج الترميز الافتراضي للتحويل إلى Unicode.

نصائح أخرى

unicode لا يخمن ترميز النص الخاص بك.إذا كان الكائن الخاص بك يمكنه طباعة نفسه كـ unicode, ، تعريف __unicode__() الطريقة التي تقوم بإرجاع سلسلة Unicode.


السر هو ذلك unicode(r) لا يتصل في الواقع __str__() بحد ذاتها.بدلا من ذلك، فإنه يبحث عن __unicode__() طريقة.التنفيذ الافتراضي ل __unicode__() سوف اتصل __str__() ثم حاول فك تشفيره باستخدام ملف ascii مجموعة محارف.عندما تقوم بتمرير الترميز، unicode() يتوقع أن يكون الكائن الأول شيئًا يمكن فك تشفيره - أي مثيل لـ basestring.


السلوك غريب لأنه يحاول فك التشفير كـ ascii إذا لم أتمكن من اجتياز "utf-8".ولكن إذا قمت بتمرير "utf-8" فإنه يعطي خطأً مختلفًا ...

وذلك لأنه عند تحديد "utf-8"، فإنه يعامل المعلمة الأولى ككائن يشبه السلسلة ليتم فك تشفيره.وبدون ذلك، فإنه يعامل المعلمة ككائن ليتم إجباره على يونيكود.

أنا لا أفهم الارتباك.إذا كنت تعرف أن الكائن text ستكون السمة دائمًا بتشفير UTF-8، ما عليك سوى تحديدها __unicode__() وبعد ذلك كل شيء سوف يعمل بشكل جيد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top