如何以固定宽度打印字符串?

Posted

技术标签:

【中文标题】如何以固定宽度打印字符串?【英文标题】:How to print a string at a fixed width? 【发布时间】:2012-01-17 00:56:55 【问题描述】:

我有这段代码(打印字符串中所有排列的出现)

def splitter(str):
    for i in range(1, len(str)):
        start = str[0:i]
        end = str[i:]
        yield (start, end)
        for split in splitter(end):
            result = [start]
            result.extend(split)
            yield result    

el =[];

string = "abcd"
for b in splitter("abcd"):
    el.extend(b);

unique =  sorted(set(el));

for prefix in unique:
    if prefix != "":
        print "value  " , prefix  , "- num of occurrences =   " , string.count(str(prefix));

我想打印字符串变量中出现的所有排列。

由于排列的长度不同,我想固定宽度并以不像这样的方式打印它:

value   a - num of occurrences =    1
value   ab - num of occurrences =    1
value   abc - num of occurrences =    1
value   b - num of occurrences =    1
value   bc - num of occurrences =    1
value   bcd - num of occurrences =    1
value   c - num of occurrences =    1
value   cd - num of occurrences =    1
value   d - num of occurrences =    1

我如何使用format 来做到这一点?

我找到了这些帖子,但它不适合字母数字字符串:

python string formatting fixed width

Setting fixed length with python

【问题讨论】:

print '%10s' % 'mystring' 怎么样 很惊讶"\t" 并未在任何解决方案中列为选项。 【参考方案1】:

我发现使用str.format 更优雅:

>>> '0: <5'.format('s')
's    '
>>> '0: <5'.format('ss')
'ss   '
>>> '0: <5'.format('sss')
'sss  '
>>> '0: <5'.format('ssss')
'ssss '
>>> '0: <5'.format('sssss')
'sssss'

如果您想将字符串对齐到正确的位置,请使用 &gt; 而不是 &lt;

>>> '0: >5'.format('ss')
'   ss'

编辑 1: 如 cmets 中所述:'0: &lt;5' 中的 0 表示传递给 str.format() 的参数索引。


编辑 2: 在 python3 中,也可以使用 f 字符串:

sub_str='s'
for i in range(1,6):
    s = sub_str*i
    print(f's:>5')
    
'    s'
'   ss'
'  sss'
' ssss'
'sssss'

或:

for i in range(1,5):
    s = sub_str*i
    print(f's:<5')
's    '
'ss   '
'sss  '
'ssss '
'sssss'

值得注意的是,在上面的某些地方,添加了' '(单引号)以强调打印字符串的宽度。

【讨论】:

另外,0 表示格式参数的位置,所以你可以做另外两件事:'&lt;5'.format('ss') 'ss ' 就像以前一样,但没有 0,做同样的事情或@987654335 @'Second sss and first ss ' 这样您就可以在单个输出字符串中多次重新排序甚至输出相同的变量。 我无法再编辑之前的评论,需要它。 &lt;5 不起作用,但 : &lt;5 在没有索引值的情况下确实起作用。 这是描述这些格式字符串和其他选项的 Python Format Specification Mini-Language。为了快速参考,0: &lt;5 中的空格是 [fill]&lt;[align]5[width] 那个5可以是变量替换&gt;&gt;&gt; print width 20 &gt;&gt;&gt; print "0: &lt;width".format("ssssss", width=width).split('\n') ['ssssss '] &gt;&gt;&gt; 您也可以使用数字并按顺序列出变量width=10; "0: &lt;1".format('sss', width)。甚至可以省略数字': &lt;'.format('sss', width)【参考方案2】:

EDIT 2013-12-11 - 这个答案很老了。它仍然有效且正确,但查看此内容的人应该更喜欢new format syntax。

你可以像这样使用string formatting:

>>> print '%5s' % 'aa'
   aa
>>> print '%5s' % 'aaa'
  aaa
>>> print '%5s' % 'aaaa'
 aaaa
>>> print '%5s' % 'aaaaa'
aaaaa

基本上:

% 字符通知 python 它必须将某些东西替换为令牌 s 字符通知 python 令牌将是一个字符串 5(或您希望的任何数字)通知 python 用最多 5 个字符的空格填充字符串。

在您的具体情况下,可能的实现可能如下所示:

>>> dict_ = 'a': 1, 'ab': 1, 'abc': 1
>>> for item in dict_.items():
...     print 'value %3s - num of occurances = %d' % item # %d is the token of integers
... 
value   a - num of occurances = 1
value  ab - num of occurances = 1
value abc - num of occurances = 1

旁注:只是想知道您是否知道itertools module 的存在。例如,您可以在一行中获取所有组合的列表:

>>> [''.join(perm) for i in range(1, len(s)) for perm in it.permutations(s, i)]
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'ba', 'bc', 'bd', 'ca', 'cb', 'cd', 'da', 'db', 'dc', 'abc', 'abd', 'acb', 'acd', 'adb', 'adc', 'bac', 'bad', 'bca', 'bcd', 'bda', 'bdc', 'cab', 'cad', 'cba', 'cbd', 'cda', 'cdb', 'dab', 'dac', 'dba', 'dbc', 'dca', 'dcb']

您可以通过将combinationscount() 结合使用来获取出现次数。

【讨论】:

您也许应该提到负数给出左对齐的填充输出;这对初学者来说很难直观。 +1 for @tripleee,如果没有你的负数给出左对齐的评论,我会更长时间地打我的头......谢谢 m8。 这比新的 str.format 更加直观和简洁。我不明白为什么 python 会推动卷积 有没有办法用特定字符填充空格?例如,如果我们需要打印“05”而不是“5” 这里有更多技巧,可以在Medium 上使用 f 字符串进行优雅的固定宽度打印。【参考方案3】:

最初作为对@0x90 答案的编辑发布,但因偏离帖子的原意而被拒绝,并建议作为评论或答案发布,因此我在此处包含简短的文章。

除了来自@0x90 的答案之外,语法可以更加灵活,通过使用宽度变量(根据@user2763554 的评论):

width=10
'0: <width'.format('sss', width=width)

此外,您可以通过仅使用数字并依赖传递给format 的参数的顺序来简化此表达式:

width=10
'0: <1'.format('sss', width)

或者甚至省略所有数字以获得最大的、潜在的非 Python 隐式的紧凑性:

width=10
': <'.format('sss', width)

2017-05-26 更新

使用 Python 3.6 中的the introduction of formatted string literals(简称“f-strings”),现在可以使用更简洁的语法访问之前定义的变量:

>>> name = "Fred"
>>> f"He said his name is name."
'He said his name is Fred.'

这也适用于字符串格式

>>> width=10
>>> string = 'sss'
>>> f'string: <width'
'sss       '

【讨论】:

我真的很喜欢这个答案!【参考方案4】:

format 绝对是最优雅的方式,但是你不能将它与 python 的 logging 模块一起使用,所以这里是你可以使用 % 格式的方法:

formatter = logging.Formatter(
    fmt='%(asctime)s | %(name)-20s | %(levelname)-10s | %(message)s',
)

这里-表示左对齐,s前面的数字表示固定宽度。

一些示例输出:

2017-03-14 14:43:42,581 | this-app             | INFO       | running main
2017-03-14 14:43:42,581 | this-app.aux         | DEBUG      | 5 is an int!
2017-03-14 14:43:42,581 | this-app.aux         | INFO       | hello
2017-03-14 14:43:42,581 | this-app             | ERROR      | failed running main

更多信息请参阅此处的文档:https://docs.python.org/2/library/stdtypes.html#string-formatting-operations

【讨论】:

这不会缩短超过 20 个字符的字符串。使用 '%(name)20.20s' 将 20 设置为最小和最大字符串长度!【参考方案5】:
>>> print(f"'123':<456789")
123 56789

【讨论】:

【参考方案6】:

当您想在一个打印语句中打印多个元素时,这将有助于保持固定长度。

25s 格式化一个包含 25 个空格的字符串,默认左对齐。

5d 格式化一个保留 5 个空格的整数,默认右对齐。

members=["Niroshan","Brayan","Kate"]
print("__________________________________________________________________")
print(':25s :32s :35s '.format("Name","Country","Age"))
print("__________________________________________________________________")
print(':25s :30s :5d '.format(members[0],"Srilanka",20))
print(':25s :30s :5d '.format(members[1],"Australia",25))
print(':25s :30s :5d '.format(members[2],"England",30))
print("__________________________________________________________________")

这会打印出来

__________________________________________________________________
Name                      Country                          Age
__________________________________________________________________
Niroshan                  Srilanka                          20
Brayan                    Australia                         25
Kate                      England                           30
__________________________________________________________________

【讨论】:

【参考方案7】:

我发现ljust()rjust() 对于以固定宽度或fill out a Python string with spaces 打印字符串非常有用。

一个例子

print('123.00'.rjust(9))
print('123456.89'.rjust(9))

# expected output  
   123.00
123456.89

对于您的情况,您的情况使用fstring 打印

for prefix in unique:
    if prefix != "":
        print(f"value  prefix.ljust(3) - num of occurrences = string.count(str(prefix))")

预期输出

value  a   - num of occurrences = 1
value  ab  - num of occurrences = 1
value  abc - num of occurrences = 1
value  b   - num of occurrences = 1
value  bc  - num of occurrences = 1
value  bcd - num of occurrences = 1
value  c   - num of occurrences = 1
value  cd  - num of occurrences = 1
value  d   - num of occurrences = 1

您可以将3 更改为排列字符串的最大长度。

【讨论】:

以上是关于如何以固定宽度打印字符串?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Intermec 打印语言版本 12 在字段中居中非固定宽度字体

如何缩小字体以适应 Android 中视图的内部宽度?

在 Golang 中以最小宽度浮动到字符串

Graphics.DrawString 以打印文档宽度为中心

如何解压字符串 - 使用 sprintf 创建 - 在 Perl 中具有固定宽度

将以逗号分隔格式保存的数据转换为不带包的固定宽度格式