打印obj和print obj .__ str __()之间的Python差异[至少用Unicode?]

时间:2012-07-03 19:26:30

标签: python unicode

我被告知要调用print obj会调用obj.__str__(),而print obj.__str__() print obj.__repr__() 会返回一个字符串以打印到控制台。现在我遇到了Unicode的问题,我无法打印任何非ascii字符。我得到了典型的“ascii超出范围”的东西。

在尝试以下工作时:

__str__()

两个函数完全相同(self.__repr__()只返回print obj )。什么行不通:

__str__()

仅在使用ascii范围之外的字符时才会出现问题。最终解决方案是return self.__repr__().encode(sys.stdout.encoding)

中的以下内容
cp850

现在它适用于所有部件。我现在的问题是:区别在哪里?为什么现在有效?如果没有任何效果我会得到,为什么现在这样。但为什么只有顶部工作,而不是底部。

操作系统是Windows 7 x64,带有默认的Windows命令提示符。此外,编码报告为str(obj)。这是理解python的一般问题。我的问题已经解决了,但我并不是百分之百满意,主要是因为现在调用# -*- coding: utf-8 -*- class Sample(object): def __init__(self): self.name = u"üé" def __repr__(self): return self.name def __str__(self): return self.name obj = Sample() print obj.__str__(), obj.__repr__(), obj 会产生一个不按我想要的方式编码的字符串。

obj

删除最后一个UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) 并且它有效。保持它并与它崩溃

{{1}}

2 个答案:

答案 0 :(得分:4)

我的猜测是,对于要打印的对象obj,打印会执行以下操作:

  1. 检查obj是否为unicode。如果是,则将其编码为sys.stdout.encoding并打印。
  2. 检查obj是否为str。如果是这样,请直接打印。
  3. 如果obj是其他内容,请拨打str(obj)并打印出来。
  4. 第1步是print obj.__str__()适用于您的情况。

    现在,str(obj)做的是:

    1. 致电obj.__str__()
    2. 如果结果是str,请将其返回
    3. 如果结果为unicode,则将其编码为"ascii"并返回
    4. 否则,一些事情大多无用。
    5. 直接调用obj.__str__()会跳过步骤2-3,这就是您无法解决编码问题的原因。

      问题不是由print的工作方式引起的,而是由str()的工作方式引起的。 str()忽略sys.stdout.encoding。由于它不知道你想对结果字符串做什么,所以它使用的默认编码可以被认为是任意的; ascii与任何选择一样好或坏。

      要防止此错误,请确保从str返回__str__(),因为文档要求您这样做。可以用于Python 2.x的模式可能是:

      class Foo():
          def __unicode__(self):
              return u'whatever'
          def __str__(self):
              return unicode(self).encode(sys.stdout.encoding)
      

      (如果你确定除了打印到控制台之外什么都不需要str()表示。)

答案 1 :(得分:1)

首先,如果您查看the online documentation__str____repr__有不同的目的,应创建不同的输出。因此,从__repr__调用__str__并非最佳解决方案。

其次,print将调用__str__并且不会期望接收非ascii字符,因为,print无法猜测如何转换非ascii字符。

最后,在Python 2.x的最新版本中,__unicode__是为对象创建字符串表示的首选方法。 Python str versus unicode中有一个有趣的解释。

所以,要尝试真正回答这个问题,你可以这样做:

class Sample(object):

    def __init__(self):
        self.name = u"\xfc\xe9"

    # No need to implement __repr__. Let Python create the object repr for you

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return self.name