1

ご存知のように、Python は文字列の書式設定をサポートしていますが、Python 2 でそれがどのように実現されたかについてお話したいと思いa=u'абв'; b='abc'; c='%s%s'ますcmyobject変数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== strPython 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

を実装する必要があります__format__

于 2012-08-22T18:10:54.993 に答える