以 str.format 切片字符串

问题描述 投票:0回答:7

我想通过

str.format
实现以下目标:

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

我能做到的唯一方法是:

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

现在,这是一个例子,我真正拥有的是一个又长又乱的字符串,所以我想将切片放在

{}
中。我已经研究了文档,但我无法找出正确的语法。我的问题是:是否可以在替换字段内对字符串进行切片?

python string string-formatting
7个回答
19
投票

不,您不能对替换字段内的字符串应用切片。

您需要参考格式规范迷你语言;它定义了“什么是”可能。这种迷你语言定义了如何格式化引用值(替换字段语法中:之后的部分)。

    


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

不支持像 [:5]

[6:]
这样的切片,但我认为这也很容易实现。此外,也没有对切片索引超出范围等进行错误检查。
    


2
投票

你也不能给字符串类型加一,因为内置的Python类型不能被修改/扩展。

请参阅

https://stackoverflow.com/a/49884004/627042

,了解运行时计算 f 字符串的示例。


2
投票

解决方法

之前扩展

string.Formatter

的答案并不完全正确,因为重载 get_value 并不是向 string.Formatter 添加切片机制的正确方法。 import string def transform_to_slice_index(val: str): if val == "_": return None else: return int(val) class SliceFormatter(string.Formatter): def get_field(self, field_name, args, kwargs): slice_operator = None if type(field_name) == str and '|' in field_name: field_name, slice_indexes = field_name.split('|') slice_indexes = map(transform_to_slice_index, slice_indexes.split(',')) slice_operator = slice(*slice_indexes) obj, first = super().get_field(field_name, args, kwargs) if slice_operator is not None: obj = obj[slice_operator] return obj, first

解释

get_value

get_field 中调用,它仅用于从 vformat() 访问 args 和 kwargs。 attr 和项目访问是在 get_field 中完成的。因此,切片访问应该在 super().get_field 返回所需的 obj 之后完成。 话虽如此,重载 get_value 会带来一个问题,即在遍历对象后格式化程序无法进行切片。您可以在这个示例中看到错误:

WrongSliceFormatter().format("{foo.bar[0]|1,3}", foo=foo) >> ValueError: "Only '.' or '[' may follow ']' in format field specifier"



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

作为示例,可以组合所有三种格式规范来剪辑值的第一个和最后一个字符,将切片居中删除为 10 个字符的值,最后在 12 个字符的字段中将其右对齐,如下所示:

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

输出:'ente**value'。对于其他可能感兴趣的人。非常感谢。


0
投票
new_template = '{old[0]} is {old[2:]}'

这样的f字符串, 希望使用

new = template.format(old=old)
,但行不通。
如果你遇到类似的情况,你可以只使用一组 lambda,

new_maker = lambda old: f'{old[0]} is {old[2:]}'

,像

new = new_maker(old)
一样使用它
    


-1
投票

x="nowpossible" print(" slicing is possible {}".format(x[0:2]))

输出

slicing is possible now

© www.soinside.com 2019 - 2024. All rights reserved.