أفضل ممارسات نوع الإخراج وممارسات الترميز لوظائف __repr __ ()؟
سؤال
في الآونة الأخيرة ، واجهت الكثير من المتاعب __repr__()
, format()
, والترميزات. يجب أن يكون إخراج __repr__()
تكون مشفرة أو تكون سلسلة يونيكود؟ هل هناك أفضل ترميز لنتيجة __repr__()
في بيثون؟ ما أريد إخراجه لديه أحرف غير ASCII.
أستخدم Python 2.x ، وأريد كتابة رمز يمكن تكييفه بسهولة مع Python 3. يستخدم البرنامج بالتالي
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function # The 'Hello' literal represents a Unicode object
فيما يلي بعض المشكلات الإضافية التي كانت تزعجني ، وأنا أبحث عن حل يحلها:
- يجب أن تعمل الطباعة على محطة UTF-8 (لدي
sys.stdout.encoding
ضبط لUTF-8
, ، ولكن سيكون من الأفضل إذا نجحت حالات أخرى أيضًا). - يجب أن تعمل الأنابيب إلى ملف (مشفر في UTF-8) (في هذه الحالة ،
sys.stdout.encoding
هوNone
). - رمزتي للكثيرين
__repr__()
الوظائف حاليا لديها الكثيرreturn ….encode('utf-8')
, ، وهذا ثقيل. هل هناك أي شيء قوي وأخف وزنا؟ - في بعض الحالات ، لدي وحوش قبيحة مثل
return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')
, ، أي ، تم فك تشفير تمثيل الكائنات ، ووضعه في سلسلة تنسيق ، ثم إعادة ترميزها. أود تجنب مثل هذه التحولات المعقدة.
ما الذي تنصح به من أجل الكتابة البسيطة __repr__()
الوظائف التي تتصرف بشكل جيد فيما يتعلق بهذه الأسئلة الترميز؟
المحلول
في Python2 ، __repr__
(و __str__
) يجب إرجاع كائن سلسلة ، وليس كائن Unicode. في Python3 ، يتم عكس الوضع ، __repr__
و __str__
يجب إرجاع كائنات Unicode ، وليس الكائنات البايت (Née String):
class Foo(object):
def __repr__(self):
return u'\N{WHITE SMILING FACE}'
class Bar(object):
def __repr__(self):
return u'\N{WHITE SMILING FACE}'.encode('utf8')
repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u263a' in position 0: ordinal not in range(128)
في Python2 ، ليس لديك خيار حقًا. عليك اختيار ترميز لقيمة الإرجاع __repr__
.
بالمناسبة ، هل قرأت printfails wiki؟ قد لا يجيب بشكل مباشر على أسئلتك الأخرى ، لكنني وجدت أنه مفيد في إلقاء الضوء على سبب حدوث بعض الأخطاء.
عند استخدام from __future__ import unicode_literals
,
'<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')
يمكن أن يكون أكثر كتابًا أكثر من ذلك
str('<{}>').format(repr(x))
على افتراض str
يشفر إلى utf-8
على نظامك.
بدون from __future__ import unicode_literals
, ، يمكن كتابة التعبير على النحو التالي:
'<{}>'.format(repr(x))
نصائح أخرى
أعتقد أن الديكور يمكن أن يديره __repr__
عدم التوافق بطريقة عاقلة. هذا ما أستخدمه:
from __future__ import unicode_literals, print_function
import sys
def force_encoded_string_output(func):
if sys.version_info.major < 3:
def _func(*args, **kwargs):
return func(*args, **kwargs).encode(sys.stdout.encoding or 'utf-8')
return _func
else:
return func
class MyDummyClass(object):
@force_encoded_string_output
def __repr__(self):
return 'My Dummy Class! \N{WHITE SMILING FACE}'
أستخدم وظيفة مثل ما يلي:
def stdout_encode(u, default='UTF8'):
if sys.stdout.encoding:
return u.encode(sys.stdout.encoding)
return u.encode(default)
ثم بلدي __repr__
الوظائف تبدو هكذا:
def __repr__(self):
return stdout_encode(u'<MyClass {0} {1}>'.format(self.abcd, self.efgh))