python - “%s”% myobject : overloading

标签 python string format

正如你所知,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)

这是我笔记本电脑上的代码示例。对于 Python 3,string == str;对于 Python 2,unicode。只是向后兼容。

这就是我想要得到的。

>>> 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!

最佳答案

我不太清楚你的意思,但你可以定义 __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去解析一个运算符(任何运算符)时,它会查看运算符左侧的对象并询问“这个对象是否为该对象提供了合适的实现”运算符(operator)?”。如果答案是肯定的,则 python 调用该实现并返回结果。如果答案是否定的,它会查看运算符(operator)右侧的对象并询问相同的问题。如果答案是肯定的,它将调用正确对象的实现并返回结果。如果答案是否定的,则会引发异常。

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

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

或类似的情况,%o 将以某种方式被“myobj.data”替换。最终,这变得非常困惑,我认为有必要问一下为什么要这样做?。 (您可以提供一个便利的功能来非常轻松地完成所有这些)。

我对这个主题的最后评论是,您可能想考虑覆盖 template用于字符串格式化。它不经常使用,但可能在这里有用......

关于python - “%s”% myobject : overloading,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12078948/

相关文章:

python - 使用 beautiful soup 的基本网页抓取 : scrape a table

python - 如何读取 Dropbox 上超过 2000 个文件的路径?

c++ - 一次两个字符串算法?

file - 如何使用元数据创建文件格式

dart - VSCode 为数组等的代码格式设置宽度

python - 调用表单 python 脚本时,bash 脚本不读取行

python - 忽略 KeyError 并继续程序

评估用户输入时代码无法继续

java - 在java中生成List字符串的组合

c++ - 简单的 c++ cout 语句,一行有格式问题,这是什么?