13

什么会产生以下行为?

>>> print str(msg)
my message
>>> print unicode(msg)
my message

但:

>>> print '%s' % msg
another message

更多信息:

  • 我的msg对象继承自unicode.
  • 方法__str__//方法被覆盖以返回字符串__unicode____repr__'my message'
  • msg对象是用字符串初始化的'another message'
  • 这是在 python 2.5 上运行的
  • 变量msg在测试之间没有改变
  • 这实际上是真正给出这些结果的真正 doctest。

我想要一个与这个 doctest 相匹配的解决方案,并尽量减少大惊小怪(尤其是在实际继承方面):

>>> print '%s' % msg
my message

感谢所有建议。

我觉得这不会有更多帮助,但对于好奇的读者(和喜欢冒险的 pythonist),这里是对象的实现:

class Message(zope.i18nmessageid.Message):

    def __repr__(self):
        return repr(zope.i18n.interpolate(self.default, self.mapping))

    def __str__(self):
        return zope.i18n.interpolate(self.default, self.mapping)

    def __unicode__(self):
        return zope.i18n.interpolate(self.default, self.mapping)

这就是我们创建对象 msg 的方式:

>>> msg = Message('another message', 'mydomain', default='my message')

Zope 软件包版本和使用的代码是:

编辑信息:

  • 添加/更新了被覆盖的方法的名称
  • 添加了更多信息(python 版本和次要信息)
  • 更新了一些错误信息(`msg` 的类是基于 `unicode` 类而不是 `basestring`)
  • 添加了使用的类的实际实现
4

3 回答 3

8

更新 2:请在水平条下方找到原始答案,包括展示 OP 描述的行为的类的简单示例。至于我在调查 Python 的源代码(v. 2.6.4)的过程中能够推测出什么:

该文件Include/unicodeobject.h包含以下行(我的(有点旧的)结帐中的第 436-7 号):

#define PyUnicode_AS_UNICODE(op) \                                              
        (((PyUnicodeObject *)(op))->str)

这在格式化代码中到处使用,据我所知,这意味着在字符串格式化期间,unicode将访问任何继承自的对象,以便可以直接使用其 unicode 字符串缓冲区,而无需调用任何Python 方法。我敢肯定,就性能而言,这很好(并且非常符合 Juergen 在对此答案的评论中的猜想)。

对于 OP 的问题,这可能意味着只有在此特定用例可以接受诸如 Anurag Uniyal 的包装类理念之类的东西时,才能使事情按照 OP 希望的方式工作。如果不是,那么我现在唯一想到的就是将此类的对象包装在str/unicode将它们插入字符串的任何位置......呃。(我真诚地希望我只是错过了一个更清洁的解决方案,有人会在一分钟内指出!)


更新:这是在 OP 包含他的课程代码之前大约一分钟发布的,但我还是把它留在这里(1)用于猜想/最初尝试在代码下方进行解释,(2)用于简单示例如何产生这种行为(Anurag Uniyal 此后直接提供了另一个调用unicode的构造函数,而不是 via super),(3)希望以后能够编辑某些内容以帮助 OP 获得所需的行为。)

这是一个类的示例,它实际上像 OP 描述的那样工作(Python 2.6.4,它确实会产生弃用警告 -- /usr/bin/ipython:3: DeprecationWarning: object.__init__() takes no parameters):

class Foo(unicode):
    def __init__(self, msg):
        super(unicode, self).__init__(msg)
    def __str__(self): return 'str msg'
    def __repr__(self): return 'repr msg'
    def __unicode__(self): return u'unicode msg'

IPython 中的一些交互:

In [12]: print(Foo("asdf"))
asdf

In [13]: str(Foo("asdf"))
Out[13]: 'str msg'

In [14]: print str(Foo("asdf"))
-------> print(str(Foo("asdf")))
str msg

In [15]: print(str(Foo("asdf")))
str msg

In [16]: print('%s' % Foo("asdf"))
asdf

显然,字符串插值将此对象视为unicode(直接调用 的unicode实现__str__)的实例,而其他函数将其视为 的实例Foo。这是如何在内部发生的,为什么会这样工作,以及它是错误还是功能,我真的不知道。

至于如何修复OP的对象......好吧,我怎么知道没有看到它的代码???给我代码,我保证会考虑一下!好的,我正在考虑它......到目前为止没有任何想法。

于 2010-02-22T16:17:07.223 回答
6

所以问题是类似于下面的东西的类行为怪异

class Msg(unicode):
    def __init__(self, s):
        unicode.__init__(self, s)

    __unicode__ = __repr__ = __str__ = lambda self: "my message"

msg = Msg("another message")
print str(msg)
print unicode(msg)
print "%s"%msg

这打印

my message
my message
another message

我不确定为什么会发生这种情况或如何解决它,但是通过包装 Msg 进行了非常粗略的尝试,但不确定它是否有助于解决 OP 的问题

class MsgX(object):
    def __init__(self, s):
        self._msg = Msg(s)

    __unicode__ = __repr__ = __str__ = lambda self: repr(self._msg)

msg = MsgX("another message")
print str(msg)
print unicode(msg)
print "%s"%msg

输出:

my message
my message
my message
于 2010-02-22T16:21:22.920 回答
3

我认为您的问题是您正在尝试扩展内置。__内置函数不会调用魔术方法。我认为你将不得不做某种包装和委托,像这样(未经测试)(也许阿努拉格打败了我):

class Message(object): 

    def __init__(self, strvalue, domain, default='my message'):
        self.msg = zope.i18nmessageid.Message(strvalue,domain,default)

    def __getattr__(self,attr):
        return getattr(self.msg,attr)

    def __repr__(self): 
        return repr(zope.i18n.interpolate(self.msg.default, self.msg.mapping)) 

    def __str__(self): 
        return zope.i18n.interpolate(self.msg.default, self.msg.mapping) 

    def __unicode__(self): 
        return zope.i18n.interpolate(self.msg.default, self.msg.mapping) 

更新 1 - 似乎确实为内置函数的子类调用了__方法

>>> class Z(int):
...   def __add__(self,other): return self*other
...   def __str__(self): return "***"
...
>>> a = Z(100)
>>> a + 2
200
>>> a
100
>>> str(a)
'***'
>>> "%s" % a
'***'

所以肯定有一些不一致的地方......

于 2010-02-22T16:45:24.513 回答