使用 python 3.5 str.format 左截断?
Left truncate using python 3.5 str.format?
问:是否可以使用 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)
我要left_truncate"git_sha"环境变量。不可否认,这比最简单的形式复杂一点,但如果我能解决最简单的问题——我就能找到解决更复杂问题的方法。
子类化 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))
我知道,包装器勉强可以接受,但您可以通过适当地模拟容器类型将其调整为透明。
[edit] 请参阅 Jim 的解决方案,了解不子类 str
或 dict
的变体。
这是我的解决方案,感谢@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)
问:是否可以使用 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)
我要left_truncate"git_sha"环境变量。不可否认,这比最简单的形式复杂一点,但如果我能解决最简单的问题——我就能找到解决更复杂问题的方法。
子类化 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))
我知道,包装器勉强可以接受,但您可以通过适当地模拟容器类型将其调整为透明。
[edit] 请参阅 Jim 的解决方案,了解不子类 str
或 dict
的变体。
这是我的解决方案,感谢@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)