25

で次のことを達成したいstr.format

x,y = 1234,5678
print str(x)[2:] + str(y)[:2]

私がそれを行うことができた唯一の方法は次のとおりです。

print '{0}{1}'.format(str(x)[2:],str(y)[:2])

さて、これは例であり、私が実際に持っているのは長くて乱雑な文字列であるため、{}. docsを調べましたが、正しい構文がわかりません。私の質問は: 置換フィールド内で文字列をスライスすることは可能ですか?

4

5 に答える 5

19

いいえ、置換フィールド内の文字列にスライスを適用することはできません。

Format Specification Mini-Languageを参照する必要があります。可能なことを定義します。このミニ言語は、参照される値 (:置換フィールド構文の の後の部分) をフォーマットする方法を定義します。

于 2012-12-28T16:52:02.723 に答える
8

このようなことができます。


これは大まかな例であり、完全でテスト済みと見なすべきではありません。しかし、それはあなたがなりたい場所に到達するための方法を示していると思います.

import string

class SliceFormatter(string.Formatter):

    def get_value(self, key, args, kwds):
        if '|' in key:
            try:
                key, indexes = key.split('|')
                indexes = map(int, indexes.split(','))
                if key.isdigit():
                    return args[int(key)][slice(*indexes)]
                return kwds[key][slice(*indexes)]
            except KeyError:
                return kwds.get(key, 'Missing')
        return super(SliceFormatter, self).get_value(key, args, kwds)


phrase = "Hello {name|0,5}, nice to meet you.  I am {name|6,9}.  That is {0|0,4}."
fmt = SliceFormatter()
print fmt.format(phrase, "JeffJeffJeff", name="Larry Bob")

出力

Hello Larry, nice to meet you.  I am Bob.  That is Jeff.

注 2 orの
ようなスライスはサポートされていませんが、実装も簡単だと思います。また、範囲外のスライス インデックスなどのエラー チェックもありません。[:5][6:]

于 2012-12-28T17:13:50.820 に答える
1

これは素晴らしい解決策であり、スライスの問題をうまく解決しました。ただし、値の省略も行いたいと思っていました。たとえば、10 文字のフィールドに入力したい「AVeryLongStringValue」は、「...ngValue」に切り詰められる可能性があります。そのため、スライス、省略、および通常の書式設定をすべて 1 つにサポートするように例を拡張しました。これが私が思いついたものです。

class SliceElideFormatter(string.Formatter):
    """An extended string formatter that provides key specifiers that allow
    string values to be sliced and elided if they exceed a length limit.  The
    additional formats are optional and can be combined with normal python
    formatting.  So the whole syntax looks like:
    key[|slice-options][$elide-options[:normal-options]
    Where slice options consist of '|' character to begin a slice request,
    followed by slice indexes separated by commas.  Thus {FOO|5,} requests
    everything after the 5th element.
      The elide consist of '$' character followed by an inter max field value,
    followed by '<', '^', or '>' for pre, centered, or post eliding, followed
    by the eliding string.  Thus {FOO$10<-} would display the last 9 chanacters
    of a string longer then 10 characters with '-' prefix.
      Slicing and eliding can be combined.  For example given a dict of
    {'FOO': 'centeredtextvalue', and a format string of 
    '{FOO|1,-1$11^%2E%2E%2E}' would yield 'ente...valu'.  The slice spec removes
    the first and last characrers, and the elide spec center elides the
    remaining value with '...'.  The '...' value must be encoded in URL format
    since . is an existing special format character.
    """

    def get_value(self, key, args, kwds):
        """Called by string.Formatter for each format key found in the format
        string.  The key is checked for the presence of a slice or elide intro-
        ducer character.  If one or both a found the slice and/or elide spec
        is extracted, parsed and processed on value of found with the remaining
        key string.
        Arguments:
          key, A format key string possibly containing slice or elide specs
          args, Format values list tuple
          kwds, Format values key word dictrionary
        """
        sspec = espec = None
        if '|' in key:
            key, sspec = key.split('|')
            if '$' in sspec:
                sspec, espec = sspec.split('$')
        elif '$' in key:
            key, espec = key.split('$')
        value = args[int(key)] if key.isdigit() else kwds[key]
        if sspec:
            sindices = [int(sdx) if sdx else None
                        for sdx in sspec.split(',')]
            value = value[slice(*sindices)]
        if espec:
            espec = urllib.unquote(espec)
            if '<' in espec:
                value = self._prefix_elide_value(espec, value)
            elif '>' in espec:
                value = self._postfix_elide_value(espec, value)
            elif '^' in espec:
                value = self._center_elide_value(espec, value)
            else:
                raise ValueError('invalid eliding option %r' % elidespec)
        if sspec or espec:
            return value

        return super(SliceElideFormatter,self).get_value(key, args, kwds)

    def _center_elide_value(self, elidespec, value):
        """Return center elide value if it exceeds the elide length.
        Arguments:
          elidespec, The elide spec field extracted from key
          value, Value obtained from remaing key to maybe be elided
        """
        elidelen, elidetxt = elidespec.split('^')
        elen, vlen = int(elidelen), len(value)
        if vlen > elen:
            tlen = len(elidetxt)
            return value[:(elen-tlen)//2] + elidetxt + value[-(elen-tlen)//2:]
        return value

    def _postfix_elide_value(self, elidespec, value):
        """Return postfix elided value if it exceeds the elide length.
        Arguments:
          elidespec, The elide spec field extracted from key
          value, Value obtained from remaing key to maybe be elided
        """
        elidelen, elidetxt = elidespec.split('>')
        elen, vlen  = int(elidelen), len(value)
        if vlen > elen:
            tlen = len(elidetxt)
            return value[:(elen-tlen)] + elidetxt
        return value

    def _prefix_elide_value(self, elidespec, value):
        """Return prefix elided value if it exceeds the elide length.
        Arguments:
          elidespec, The elide spec field extracted from key
          value, Value obtained from remaing key to maybe be elided
        """
        elidelen, elidetxt = elidespec.split('<')
        elen, vlen  = int(elidelen), len(value)
        if vlen > elen:
            tlen = len(elidetxt)
            return elidetxt + value[-(elen-tlen):]
        return value

例として、次のように、3 つの形式仕様すべてを組み合わせて、値の最初と最後の文字をクリップし、スライスを中央で省略して 10 文字の値にし、最後に 12 文字のフィールドで右揃えにすることができます。

sefmtr = SliceElideFormatter()
data = { 'CNT':'centeredtextvalue' }
fmt = '{CNT|1,-1$10^**:>12}'
print '%r' % sefmtr.format(fmt, *(), **data)

出力: 'ente**value'. 興味があるかもしれない他の人のために。どうもありがとう。

于 2016-09-06T18:47:18.357 に答える