簡體   English   中英

python字符串插值

[英]python string interpolation

什么會產生以下行為?

>>> 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測試之間未更改變量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”)
  • 添加了所用類的實際實現

更新2:請找到原始答案,包括一個簡單的示例,該類在水平條下方展示了OP描述的行為。 至於我在查詢Python的源代碼(第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的構造函數,而不是通過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的實例(直接調用__str__unicode實現),而其他函數將其視為Foo的實例。 我真的不知道這是如何在內部發生的,以及為什么這樣工作,以及它是錯誤還是功能。

至於如何修復OP的對象...那么,我怎么會看到它的代碼呢? 給我代碼,我保證會考慮的! 好的,我正在考慮...到目前為止還沒有想法。

所以問題是類像下面的東西表現怪異

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

我認為您的問題是您正在嘗試擴展內置功能。 內置函數不會調用魔術__方法。 我認為您將必須進行某種包裝和委托,例如這樣(未經測試)(也許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) 

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

因此肯定存在一些不一致的情況...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM