66

最近,我在 、 和 编码方面遇到了很多__repr__()麻烦format()的输出应该__repr__()被编码还是 unicode 字符串?__repr__()Python 中的结果是否有最佳编码?我要输出的确实有非 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.encoding是 is None)。
  3. 我的许多__repr__()功能的代码目前有很多return ….encode('utf-8'),而且很重。有什么坚固而轻便的东西吗?
  4. 在某些情况下,我什至有丑陋的野兽,例如return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8'),对象的表示被解码,放入格式化字符串,然后重新编码。我想避免这种复杂的转换。

为了编写简单的__repr__()函数,在这些编码问题上表现得很好,你会建议做什么?

4

3 回答 3

42

在 Python2 中,__repr__(and __str__) 必须返回一个字符串对象,而不是一个 unicode 对象。在 Python3 中,情况正好相反,__repr__必须__str__ 返回 unicode 对象,而不是字节(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))
于 2010-09-02T14:01:23.790 回答
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}'
于 2012-12-12T21:10:09.467 回答
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))
于 2012-05-17T15:59:59.150 回答