__repr __()函数的最佳输出类型和编码实践?

时间:2010-09-02 13:57:16

标签: python encoding ascii repr

最近,我在使用__repr__()format()和编码方面遇到了很多麻烦。 __repr__()的输出应该编码还是unicode字符串? Python中__repr__()的结果是否有最佳编码?我要输出的内容确实有非ASCII字符。

我使用Python 2.x,并希望编写可以轻松适应Python 3的代码。程序因此使用

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function  # The 'Hello' literal represents a Unicode object

以下是一些困扰我的其他问题,我正在寻找解决这些问题的解决方案:

  1. 打印到UTF-8终端应该有效(我sys.stdout.encoding设置为UTF-8,但最好是其他情况也能正常工作。
  2. 将输出管道传输到文件(以UTF-8编码)应该有效(在这种情况下,sys.stdout.encodingNone)。
  3. 我的许多__repr__()函数的代码目前有很多return ….encode('utf-8'),而且很重要。有什么东西强劲而轻盈吗?
  4. 在某些情况下,我甚至有像return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')这样丑陋的野兽,即对象的表示被解码,放入格式化字符串,然后重新编码。我想避免这种错综复杂的转变。
  5. 为了编写对这些编码问题表现良好的简单__repr__()函数,您建议做什么?

3 个答案:

答案 0 :(得分:41)

在Python2中,__repr__(和__str__)必须返回一个字符串对象,而不是一个 unicode对象。在Python3中,情况正好相反,__repr____str__ 必须返回unicode对象,而不是byte(née字符串)对象:

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))

答案 1 :(得分:6)

我认为装饰者可以以理智的方式管理__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}'

答案 2 :(得分:1)

我使用如下函数:

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))