【问题标题】:Python print isn't using __repr__, __unicode__ or __str__ for unicode subclass?Python print 没有使用 __repr__、__unicode__ 或 __str__ 作为 unicode 子类?
【发布时间】:2013-03-19 05:39:15
【问题描述】:

Python 打印在打印时未将 __repr____unicode____str__ 用于我的 unicode 子类。关于我做错了什么的任何线索?

这是我的代码:

使用 Python 2.5.2(r252:60911,2009 年 10 月 13 日,14:11:59)

>>> class MyUni(unicode):
...     def __repr__(self):
...         return "__repr__"
...     def __unicode__(self):
...         return unicode("__unicode__")
...     def __str__(self):
...         return str("__str__")
...      
>>> s = MyUni("HI")
>>> s
'__repr__'
>>> print s
'HI'

我不确定这是否是上述的准确近似值,只是为了比较:

>>> class MyUni(object):
...     def __new__(cls, s):
...         return super(MyUni, cls).__new__(cls)
...     def __repr__(self):
...         return "__repr__"
...     def __unicode__(self):
...         return unicode("__unicode__")
...     def __str__(self):
...         return str("__str__")
...
>>> s = MyUni("HI")
>>> s
'__repr__'
>>> print s
'__str__'

[已编辑...] 这听起来像是获取 isinstance(instance, basestring) 并提供对 unicode 返回值的控制的字符串对象的最佳方法,并且使用 unicode repr 是...

>>> class UserUnicode(str):
...     def __repr__(self):
...         return "u'%s'" % super(UserUnicode, self).__str__()
...     def __str__(self):
...         return super(UserUnicode, self).__str__()
...     def __unicode__(self):
...         return unicode(super(UserUnicode, self).__str__())
...
>>> s = UserUnicode("HI")
>>> s
u'HI'
>>> print s
'HI'
>>> len(s)
2

上面的 _str__repr_ 没有给这个例子增加任何东西,但想法是显式显示模式,根据需要进行扩展。

只是为了证明这种模式可以授予控制权:

>>> class UserUnicode(str):
...     def __repr__(self):
...         return "u'%s'" % "__repr__"
...     def __str__(self):
...         return "__str__"
...     def __unicode__(self):
...         return unicode("__unicode__")
... 
>>> s = UserUnicode("HI")
>>> s
u'__repr__'
>>> print s
'__str__'

想法?

【问题讨论】:

  • 你的代码真的像第一个例子那样缩进吗?
  • 我不得不猜测你的问题是什么。如果我弄错了,请务必更新您的帖子以包含一个实际、明确的问题
  • 虽然这是一个很好的陷阱,但我想问一下为什么在 h*** 中你想继承 str 或 unicode?我的意思是,数据将是不可变的,因此生成的对象将毫无用处。
  • 我在 [Edited...] 之后添加了更多内容。感觉很恶心,但我认为它没有打破任何 Pythonic 的期望。 repr 是一个字符串表示形式,如果需要,可以用来构建一个 unicode 对象,对吧?
  • @Kay:一点用处都没有。我已经使用它为 3D 图形软件包创建名称约定对象模型。基本上使名称成为一种特殊类型的字符串,它封装了使用约定的实用程序,但仍然可以透明地传递给本机 API。 3D 应用程序主要是 unicode,所以我试图保持一致。但是,在这个线程的情况下,我包装了一个 API 对象,我希望我的类的返回值是动态的,所以它只模仿一个真正的字符串 - 只需要传递 isinstance(instance, basestring)...don不要问...

标签: python class unicode subclass derived-class


【解决方案1】:

您正在继承unicode

它永远不会调用__unicode__,因为它已经是 unicode。相反,这里发生的是对象被 编码stdout 编码:

>>> s.encode('utf8')
'HI'

除了它将使用直接 C 调用而不是 .encode() 方法。这是 print 对于 unicode 对象的默认行为。

print 语句调用PyFile_WriteObject,而后者在处理unicode 对象时又调用PyUnicode_AsEncodedString。后者然后根据当前编码的 an 编码函数,这些使用Unicode C macros 直接访问数据结构。你不能从 Python 中截取它。

我猜你正在寻找的是一个__encode__ 钩子。由于这已经是unicode 的子类,print 只需要编码,而不是将其转换为unicode 再次,也不能在不显式编码的情况下将其转换为字符串。您必须与 Python 核心开发人员一起讨论这个问题,看看 __encode__ 是否有意义。

【讨论】:

  • @nneonneo:不确定我是否同意。 :-)
  • 嗯,为什么它不是一个错误?在 Python 2.7 中对strunicode 的处理应该是比较统一的。
  • @nneonneo:将unicode 转换为str 进行打印需要编码。将任何其他内容转换为字符串需要调用__str__。请注意 OP 帖子中的第二个示例;打印自定义对象使用 __str__not __unicode__
  • @Rafe: 但__unicode__ 用于将某些东西转换为 unicode。 unicode(yourtype) 肯定会调用它。但是print 没有转换,而是 encoding 。您可能想要覆盖编码行为,但目前没有钩子。作为一项新功能,您必须在 Python 开发人员或想法列表中讨论它。
  • @Martijn:这是有道理的,但问题不是 unicode 子类在打印时忽略了 str 吗?这就是我觉得它像一个错误的地方。如果它不忽略 str 我会很高兴。我还没有理解你的意思吗?
【解决方案2】:

问题是print 不尊重__str__ 上的unicode 子类。

来自PyFile_WriteObject,被print使用:

int
PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
{
...
        if ((flags & Py_PRINT_RAW) &&
    PyUnicode_Check(v) && enc != Py_None) {
    char *cenc = PyString_AS_STRING(enc);
    char *errors = fobj->f_errors == Py_None ? 
      "strict" : PyString_AS_STRING(fobj->f_errors);
    value = PyUnicode_AsEncodedString(v, cenc, errors);
    if (value == NULL)
        return -1;

PyUnicode_Check(v) 如果v 的类型是unicode 或子类,则返回true。因此,此代码直接编写 unicode 对象,无需咨询 __str__

请注意,继承 str 并覆盖 __str__ 可以按预期工作:

>>> class mystr(str):
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
... 
>>> print mystr()
str

就像显式调用 strunicode 一样:

>>> class myuni(unicode):
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
...     def __unicode__(self): return "unicode"
... 
>>> print myuni()

>>> str(myuni())
'str'
>>> unicode(myuni())
u'unicode'

我相信这可以解释为当前实现的 Python 中的一个错误。

【讨论】:

    猜你喜欢
    • 2010-11-21
    • 1970-01-01
    • 2012-07-04
    • 2017-08-06
    • 2013-08-13
    • 2021-03-01
    • 2021-09-11
    • 2014-08-04
    相关资源
    最近更新 更多