1

如您所知,Python 支持字符串格式化,但我想谈谈它是如何在 Python 2 中实现的。如果我们键入a=u'абв'; b='abc'; c='%s%s',那么c变量将具有 unicode 类型,因此格式化返回 unicode 对象。我是否有可能拥有自己的类myobject,其中变量c将具有myobject类型?换句话说,我可以重载这个运算符吗?答案必须适用于 Python 3 和 Python 2,但用 Python 2 来描述我想要的东西更简单。谢谢!

class ustream(object):
  '''ustream class provides an easy access for basic operations with Unicode
  streams. The main advantage of this class is that it already has built-in
  support for regular expressions and transliteration.'''
  __slots__ = ['_stream_', 'array', 'stream']

  def __init__(self, stream='', encoding=ENCODING['default']):
    '''ustream.__init__([stream[, encoding]]) -> ustream'''
    if isinstance(encoding, bstream):
      encoding = encoding.stream
    elif isinstance(encoding, ustream):
      encoding = encoding.stream
    if isinstance(stream, bytes):
      stream = stream.decode(encoding)
    elif isinstance(stream, string):
      stream = string(stream)
    elif isinstance(stream, bstream):
      stream = stream.stream.decode(encoding)
    elif isinstance(stream, ustream):
      stream = stream.stream
    else: # if unknown type
      typename = type(stream).__name__
      raise(TypeError('stream must be bytes or string, not %s' % typename))
    self._stream_ = stream

  @property
  def array(self):
    '''unicode stream as array'''
    return([ord(char) for char in self.stream])

  @property
  def stream(self):
    '''unicode stream as string'''
    return(self._stream_)

  def __mod__(self, stream):
    '''ustream.__mod__(stream) <==> ustream % stream'''
    result = self.stream % ustream(stream).stream
    result = ustream(result)
    return(result)

  def __rmod__(self, stream):
    '''ustream.__rmod__(stream) <==> stream % ustream'''
    stream = ustream(stream)
    stream = stream.stream
    result = stream % self.stream
    result = ustream(result)
    return(result)

这是我笔记本电脑的代码示例。string==str适用于 Python 3 和unicodePython 2。只是向后兼容。

这是我想要得到的。

>>> src = ustream('a stream')
>>> add = 'Hello man'
>>> result = '%s! Look here: we have %s!' % (add, src)
>>> type(result)
utstream
>>> print(result)
Hello man! Look here: we have a stream!
4

2 回答 2

2

我不太清楚您的意思,但是您可以定义__mod__ (或__rmod__)以允许类重载%运算符...


为了响应您的编辑,当我运行您的代码时:

a = stream('%s')
b = a % ('foo')
print (type(b)) #<class '__main__.stream'>

它工作得很好。有什么问题?


(并且由于上面的代码再次被编辑),这是我测试的原始代码:

class stream(object):
  def __init__(self, data):
    if isinstance(data, unicode):
      self.data = data
    elif isinstance(data, bytes):
      self.data =data.decode('UTF-8')
    else:
      raise TypeError('invalid data')
  def __mod__(self, data):
    data = stream(data).data
    result = self.data.__mod__(data)
    result = stream(result)
    return(result)

你不能得到你想要的东西的原因是因为当python去解析一个运算符(任何运算符)时,它会查看运算符左侧的对象并询问“这个对象是否为该运算符提供了合适的实现?” . 如果答案是肯定的,那么 python 调用该实现并返回结果。如果答案是否定的,它会查看操作员右侧的对象并提出相同的问题。如果答案是肯定的,它会调用正确对象的实现并返回结果。如果答案是否定的,则会引发异常。

现在在您想要的输出中,您有"this is a string"%( obj1, streamobject ). 但是,当 python 查看该表达式时,它会在左侧看到一个已定义的字符串__mod__,因此 python 将始终调用该方法而不是您的用户定义的方法。正如我在评论中所说,让您的对象优先的唯一方法是切换顺序(您的对象在字符串之前)。我明白你为什么不想这样做(很难以这种方式格式化多个项目)。你必须把它写成:

myobj % ( "this is the format string %o %d %d %d", 1, 2, 3 )  #yuck

或类似的地方%o会以某种方式被“myobj.data”取代。最终,这变得非常混乱,我认为值得问你为什么要这样做?. (您可以提供一个方便的功能来真正轻松地完成所有这些工作)。

我对这个主题的最后评论是,您可能想要研究覆盖字符串格式的模板。它不经常使用,但可能在这里有用......

于 2012-08-22T18:14:35.237 回答
1

You have to implement __format__.

于 2012-08-22T18:10:54.993 回答