python python字符串插值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2311906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 00:20:59  来源:igfitidea点击:

python string interpolation

pythonstringstring-interpolation

提问by vaab

What could generate the following behavior ?

什么会产生以下行为?

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

But:

但:

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

More info:

更多信息:

  • my msgobject is inherited from unicode.
  • the methods __str__/__unicode__/__repr__methods were overridden to return the string 'my message'.
  • the msgobject was initialised with the string 'another message'.
  • this is running on python 2.5
  • the variable msgwas not changed between the tests
  • this is actually real doctest that is really giving these results.
  • 我的msg对象是从unicode.
  • 方法__str__/ __unicode__/__repr__方法进行覆盖,以返回字符串'my message'
  • msg对象是使用字符串初始化'another message'
  • 这是在 python 2.5 上运行的
  • 变量msg在测试之间没有改变
  • 这实际上是真正给出这些结果的真正的 doctest。

I would like an solution that matches this doctest, with minimal fuss (especially around the actual inheritance):

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

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

Thanks for all suggestions.

感谢您的所有建议。

I don't feel this will help more, but for curious readers (and adventurous pythonist), here's the implementation of the object:

我认为这不会有更多帮助,但对于好奇的读者(和喜欢冒险的 Python 爱好者),这是该对象的实现:

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)

This is how we create the object msg:

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

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

Zope packages version and code used are:

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

EDIT INFO:

编辑信息:

  • added/updated the names of the methods that were overriden
  • added some more info (python version, and minor info)
  • updated some wrong info (the class of `msg` is based on `unicode` class and not `basestring`)
  • added the actual implementation of the class used
  • 添加/更新被覆盖的方法的名称
  • 添加了更多信息(python 版本和次要信息)
  • 更新了一些错误信息(`msg` 类基于`unicode` 类而不是`basestring`)
  • 添加了所用类的实际实现

采纳答案by Micha? Marczyk

Update 2:Please find the original answer, including a simple example of a class exhibiting the behaviour described by the OP, below the horizontal bar. As for what I was able to surmise in the course of my inquiry into Python's sources (v. 2.6.4):

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

The file Include/unicodeobject.hcontains the following to lines (nos. 436-7 in my (somewhat old) checkout):

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

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

This is used all over the place in the formatting code, which, as far as I can tell, means that during string formatting, any object which inherits from unicodewill be reached into so that its unicode string buffer may be used directly, without calling any Python methods. Which is good as far as performance is concerned, I'm sure (and very much in line with Juergen's conjecture in a comment on this answer).

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

For the OP's question, this probably means that making things work the way the OP would like them to may only be possible if something like Anurag Uniyal's wrapper class idea is acceptable for this particular use case. If it isn't, the only thing which comes to my mind now is to wrap objects of this class in str/ unicodewherever their being interpolated into a string... ugh. (I sincerely hope I'm just missing a cleaner solution which someone will point out in a minute!)

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



(Update:This was posted about a minute before the OP included the code of his class, but I'm leaving it here anyway (1) for the conjecture / initial attempt at an explanation below the code, (2) for a simple example of how to produce this behaviour (Anurag Uniyal has since provided another one calling unicode's constructor directly, as opposed to via super), (3) in hope of later being able to edit in something to help the OP in obtaining the desired behaviour.)

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

Here's an example of a class which actually works like what the OP describes (Python 2.6.4, it does produce a deprecation warning -- /usr/bin/ipython:3: DeprecationWarning: object.__init__() takes no parameters):

这是一个类的示例,该类的实际工作方式类似于 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'

A couple of interactions in IPython:

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

Apparently string interpolation treats this object as an instance of unicode(directly calling the unicodeimplementation of __str__), whereas the other functions treat it as an instance of Foo. How this happens internally and why it works like this and whether it's a bug or a feature, I really don't know.

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

As for how to fix the OP's object... Well, how would I know without seeing its code??? Give me the code and I promise to think about it!Ok, I'm thinking about it... No ideas so far.

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

回答by Anurag Uniyal

So problem is class like to something below behaves weirdly

所以问题是类下面的东西表现得很奇怪

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

this prints

这打印

my message
my message
another message

I am not sure why this happens or how to fix it, but a very crude attempt by wrapping Msg, but not sure it will help in OP's problem

我不确定为什么会发生这种情况或如何解决它,但是通过包装 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

output:

输出:

my message
my message
my message

回答by PaulMcG

I think your problem is that you are trying to extend a built-in. Magic __methods don't get called for builtins. I think you will have to do some kind of wrap-and-delegate, like this (untested) (maybe Anurag beat me to the punch):

我认为你的问题是你试图扩展一个内置的。__内建函数不会调用魔术方法。我认为你将不得不做某种包装和委托,像这样(未经测试)(也许 Anurag 击败了我):

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) 

Update 1- it seems that __methods doget called for subclasses of builtins

更新 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
'***'

So there is definitely some inconsistency going on...

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