python字符串插值

vaa*_*aab 13 python string string-interpolation

什么可能产生以下行为?

>>> print str(msg)
my message
>>> print unicode(msg)
my message
Run Code Online (Sandbox Code Playgroud)

但:

>>> print '%s' % msg
another message
Run Code Online (Sandbox Code Playgroud)

更多信息:

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

我想要一个与这个doctest匹配的解决方案,最小化(特别是在实际的继承周围):

>>> print '%s' % msg
my message
Run Code Online (Sandbox Code Playgroud)

谢谢你的所有建议.

我觉得这不会有更多帮助,但对于好奇的读者(和冒险的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)
Run Code Online (Sandbox Code Playgroud)

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

>>> msg = Message('another message', 'mydomain', default='my message')
Run Code Online (Sandbox Code Playgroud)

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

编辑信息:

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

Mic*_*zyk 8

更新2:请在水平条下方找到原始答案,包括展示OP描述的行为的类的简单示例.至于我在查询Python的来源(第2.6.4节)时我能够猜测的是:

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

#define PyUnicode_AS_UNICODE(op) \                                              
        (((PyUnicodeObject *)(op))->str)
Run Code Online (Sandbox Code Playgroud)

这在格式化代码中的所有地方都使用,据我所知,这意味着在字符串格式化期间,任何继承的对象都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'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

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


Anu*_*yal 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
Run Code Online (Sandbox Code Playgroud)

这打印

my message
my message
another message
Run Code Online (Sandbox Code Playgroud)

我不确定为什么会发生这种情况或者如何修复它,但是通过包装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
Run Code Online (Sandbox Code Playgroud)

输出:

my message
my message
my message
Run Code Online (Sandbox Code Playgroud)