интерполяция строк python
что может вызвать следующее поведение ?
>>> print str(msg)
my message
>>> print unicode(msg)
my message
но:
>>> print '%s' % msg
another message
Подробнее:
- мой
msg
объект унаследовано отunicode
. - методы
__str__
/__unicode__
/__repr__
методы были переопределены, чтобы возвращать строку'my message'
. - the
3 ответов
обновление 2: пожалуйста, найдите оригинальный ответ, включая простой пример класса, демонстрирующего поведение, описанное OP, ниже горизонтальной полосы. Что касается того, что я смог предположить в ходе моего исследования источников Python (V. 2.6.4):
файл Include/unicodeobject.h
содержит следующие строки (nos. 436-7 в моей (несколько старой) кассе):
#define PyUnicode_AS_UNICODE(op) \
(((PyUnicodeObject *)(op))->str)
это используется повсюду в коде форматирования, который, насколько я могу tell, означает, что во время форматирования строки любой объект, который наследуется от unicode
будет достигнут, так что его строковый буфер unicode может использоваться напрямую, без вызова каких-либо методов Python. Что хорошо, что касается производительности, я уверен (и очень в соответствии с гипотезой Юргена в комментарии к этому ответу).
для вопроса OP это, вероятно, означает, что заставить вещи работать так, как OP хотел бы, чтобы они были возможны, только если что-то вроде Идея класса оболочки Anurag Uniyal приемлема для этого конкретного случая использования. Если это не так, единственное, что приходит мне на ум сейчас, чтобы обернуть объекты этого класса в str
/ unicode
везде, где их интерполируют в строку... тьфу. (Я искренне надеюсь, что мне просто не хватает более чистого решения, которое кто-то укажет через минуту!)
(обновление: это было опубликовано за минуту до того, как ОП включил код своего класса, но я оставляю его здесь в любом случае (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
. Как это происходит внутри и почему это работает так, и является ли это ошибкой или функцией, я действительно не знаю.
как для того чтобы исправить Объект ОП... Откуда мне знать, не видя кода??? Дайте мне код и я обещаю подумать об этом! Ок, я думаю об этом... Пока никаких идей.
Итак, проблема в том, что класс, как что-то ниже, ведет себя странно
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
Я думаю, ваша проблема в том, что вы пытаетесь расширить встроенный. Магия!--2--> методы не вызываются для builtins. Я думаю, вам придется сделать что-то вроде wrap-and-delegate, как это (непроверено) (возможно, Анураг опередил меня):
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 - похоже, что __
методы do получить вызов подклассов builtins
>>> 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
'***'
таким образом, определенно существует некоторая непоследовательность...