【问题标题】:Left truncate using python 3.5 str.format?使用 python 3.5 str.format 左截断?
【发布时间】:2016-06-22 17:21:19
【问题描述】:

问:是否可以使用 Python 3.5 的字符串格式化语法创建格式字符串以左截断?

基本上我想做的就是拿一个 git SHA:

"c1e33f6717b9d0125b53688d315aff9cf8dd9977"

并且仅使用格式字符串,仅显示正确的 8 个字符:

"f8dd9977"

我尝试过的事情:

无效语法

>>> "{foo[-8:]}".format(foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977")
>>> "{foo[-8]}".format(foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977")  
>>> "{:8.-8}".format("c1e33f6717b9d0125b53688d315aff9cf8dd9977")

错误的结果

### Results in first 8 not last 8. 
>>> "{:8.8}".format("c1e33f6717b9d0125b53688d315aff9cf8dd9977")

有效但不灵活且麻烦

### solution requires that bar is always length of 40.
>>> bar="c1e33f6717b9d0125b53688d315aff9cf8dd9977"
>>> "{foo[32]}{foo[33]}{foo[34]}{foo[35]}{foo[36]}{foo[37]}{foo[38]}{foo[39]}".format(foo=bar)

类似的问题是asked, but never answered。但是我的不同之处在于我仅限于使用格式字符串,我无法更改输入参数的范围。这意味着以下是不可接受的解决方案:

>>> bar="c1e33f6717b9d0125b53688d315aff9cf8dd9977"
>>> "{0}".format(bar[-8:])

我应该澄清的另一个方面...上面解释了问题的最简单形式。在实际情况下,问题更准确地表述为:

>>> import os
>>> "foo {git_sha}".format(**os.environ)

我想在哪里左截断“git_sha”环境变量。诚然,这比最简单的形式要复杂一些,但如果我能解决最简单的问题 - 我可以找到解决更复杂问题的方法。

【问题讨论】:

  • 如果输入是一个字符串,是什么阻止了您在格式之前切掉最后一个 8 字符?
  • 在 python 3.6 中它将像 f'{s[-8:]}' 一样简单
  • @arewm 基本上我有一个配置文件,它是一个模板,我可以将环境变量替换为标题。改变环境只是一堆工作......如果我能通过格式化解决它会更容易。
  • @PadraicCunningham 那是合理的......但仅限于 Python 3.5 :-(
  • @JacquesGaudin 你错过了重点......仅格式化字符串......

标签: python string python-3.x string-formatting


【解决方案1】:

子类化str 是一种选择吗?

foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977"

class CustomStr(str):
    def __format__(self, spec):
        if spec == 'trunc_left':
            return self[-8:]
        else:
            return super().__format__(spec)

s = CustomStr(foo)

print('{}'.format(s))
print('{:trunc_left}'.format(s))

从那里,您可以执行以下操作:

import os

class CustomStr(str):
    def __format__(self, spec): 
       return self[-8:]

class OsEnvironWrapper(dict):
    def __init__(self, environ):
        self.environ = environ

    def __getitem__(self, key):
        if key == 'git_sha':
            return CustomStr(self.environ[key])
        else:
            return self.environ[key]

os_environ = OsEnvironWrapper(os.environ)
print('foo {git_sha}'.format(**os_environ))

我知道,包装器几乎不能接受,但您可以通过正确模拟容器类型将其调整为透明。

[编辑] 请参阅 Jim 的解决方案,了解不继承 strdict 的变体。

【讨论】:

  • 所以也许问题是可以通过执行str=CustomStrbasestring=CustomStr 使strCustomStr 重载吗?
  • 答案已根据os.environ 要求编辑。希望这会有所帮助。
  • 我给@JacquesGaudin 答案,因为它是最有帮助的。我不想继承 str 或 dict,而是使用他的解决方案来构建我自己的解决方案,如答案列表中所列。
【解决方案2】:

这是我的解决方案,感谢@JacquesGaudin 和#Python 上的人们提供了很多指导......

class MyStr(object):
    """Additional format string options."""
    def __init__(self, obj):
        super(MyStr, self).__init__()
        self.obj = obj

    def __format__(self, spec):
        if spec.startswith("ltrunc."):
            offset = int(spec[7:])
            return self.obj[offset:]
        else:
            return self.obj.__format__(spec)

所以这样做时有效:

>>> f = {k: MyStr(v) for k, v in os.environ.items()} 
>>> "{PATH:ltrunc.-8}".format(**f)

【讨论】:

  • 看起来不错。如果可以的话,我会将偏移量作为正整数传递,并在切片时添加减号,但这是一个细节问题。干得好。
  • 我想我会保持原样......在某些情况下,我仍然想要相同的左截断,但要知道 str 开头的偏移量而不是结尾。跨度>
猜你喜欢
  • 2014-07-27
  • 2015-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 2014-07-24
  • 2023-03-29
  • 2021-02-03
相关资源
最近更新 更多