[英]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'
初始化。 msg
測試之間未更改變量msg
我想要一個與該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軟件包的版本和代碼為:
編輯信息:
更新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.