如何用零填充字符串?

如何在数字字符串的左侧填充零,使字符串具有特定的长度?

1349682 次浏览

除了zfill之外,您还可以使用常规字符串格式:

print(f'{number:05d}') # (since Python 3.6), orprint('{:05d}'.format(number)) # orprint('{0:05d}'.format(number)) # or (explicit 0th positional arg. selection)print('{n:05d}'.format(n=number)) # or (explicit `n` keyword arg. selection)print(format(number, '05d'))

字符串格式f字串的文档。

要填充字符串:

>>> n = '4'>>> print(n.zfill(3))004

填充数字:

>>> n = 4>>> print(f'{n:03}') # Preferred method, python >= 3.6004>>> print('%03d' % n)004>>> print(format(n, '03')) # python >= 2.6004>>> print('{0:03d}'.format(n))  # python >= 2.6 + python 3004>>> print('{foo:03d}'.format(foo=n))  # python >= 2.6 + python 3004>>> print('{:03d}'.format(n))  # python >= 2.7 + python3004

字符串格式化留档

width = 10x = 5print "%0*d" % (width, x)> 0000000005

看到打印留档所有令人兴奋的细节!

Python 3. x更新(7.5年后)

最后一行现在应该是:

print("%0*d" % (width, x))

I. e.0现在是一个函数,而不是一个语句。请注意,我仍然更喜欢Old Schoolprintf()风格,因为,IMNSHO,它读起来更好,因为,嗯,我从1980年1月开始使用这种符号。一些…老狗…一些…新技巧。

只需使用字符串对象的#0方法。

此示例创建一个10个字符长度的字符串,根据需要进行填充:

>>> s = 'test'>>> s.rjust(10, '0')>>> '000000test'

对于保存为整数的邮政编码:

>>> a = 6340>>> b = 90210>>> print '%05d' % a06340>>> print '%05d' % b90210

str(n).zfill(width)将与strings、ints、floats…一起使用,并且与Python 2.x和3.x兼容:

>>> n = 3>>> str(n).zfill(5)'00003'>>> n = '3'>>> str(n).zfill(5)'00003'>>> n = '3.0'>>> str(n).zfill(5)'003.0'
>>> '99'.zfill(5)'00099'>>> '99'.rjust(5,'0')'00099'

如果你想要相反的:

>>> '99'.ljust(5,'0')'99000'

您也可以重复“0”,将其添加到str(n)并获得最右边的宽度切片。快速而肮脏的小表达式。

def pad_left(n, width, pad="0"):return ((pad * width) + str(n))[-width:]

对于使用f字串的Python 3.6+:

>>> i = 1>>> f"{i:0>2}"  # Works for both numbers and strings.'01'>>> f"{i:02}"  # Works only for numbers.'01'

对于python2.6到Python 3.5:

>>> "{:0>2}".format("1")  # Works for both numbers and strings.'01'>>> "{:02}".format(1)  # Works only for numbers.'01'

这些标准格式说明符[[fill]align][minimumwidth][0][minimumwidth]

对于那些来到这里的人来说,理解而不仅仅是一个快速的答案。我特别为时间字符串做这些:

hour = 4minute = 3"{:0>2}:{:0>2}".format(hour,minute)# prints 04:03
"{:0>3}:{:0>5}".format(hour,minute)# prints '004:00003'
"{:0<3}:{:0<5}".format(hour,minute)# prints '400:30000'
"{:$<3}:{:#<5}".format(hour,minute)# prints '4$$:3####'

“0”符号用“2”填充字符替换什么,默认为空格

">"符号将所有2个"0"字符对齐到字符串的左侧

":"符号format_spec

快速计时比较:

setup = '''from random import randintdef test_1():num = randint(0,1000000)return str(num).zfill(7)def test_2():num = randint(0,1000000)return format(num, '07')def test_3():num = randint(0,1000000)return '{0:07d}'.format(num)def test_4():num = randint(0,1000000)return format(num, '07d')def test_5():num = randint(0,1000000)return '{:07d}'.format(num)def test_6():num = randint(0,1000000)return '{x:07d}'.format(x=num)def test_7():num = randint(0,1000000)return str(num).rjust(7, '0')'''import timeitprint timeit.Timer("test_1()", setup=setup).repeat(3, 900000)print timeit.Timer("test_2()", setup=setup).repeat(3, 900000)print timeit.Timer("test_3()", setup=setup).repeat(3, 900000)print timeit.Timer("test_4()", setup=setup).repeat(3, 900000)print timeit.Timer("test_5()", setup=setup).repeat(3, 900000)print timeit.Timer("test_6()", setup=setup).repeat(3, 900000)print timeit.Timer("test_7()", setup=setup).repeat(3, 900000)

> [2.281613943830961, 2.2719342631547077, 2.261691106209631]> [2.311480238815406, 2.318420542148333, 2.3552384305184493]> [2.3824197456864304, 2.3457239951596485, 2.3353268829498646]> [2.312442972404032, 2.318053102249902, 2.3054072168069872]> [2.3482314132374853, 2.3403386400002475, 2.330108825844775]> [2.424549090688892, 2.4346475296851438, 2.429691196530058]> [2.3259756401716487, 2.333549212826732, 2.32049893822186]

我对不同的重复进行了不同的测试。差异并不大,但在所有测试中,zfill的解决方案是最快的。

用左边的零填充数字字符串的最Pythonic方法是什么,即,使数字字符串具有特定的长度?

#0就是为了做到这一点:

>>> '1'.zfill(4)'0001'

请注意,它专门用于根据请求处理数字字符串,并将+-移动到字符串的开头:

>>> '+1'.zfill(4)'+001'>>> '-1'.zfill(4)'-001'

以下是str.zfill的帮助:

>>> help(str.zfill)Help on method_descriptor:
zfill(...)S.zfill(width) -> str
Pad a numeric string S with zeros on the left, to fill a fieldof the specified width. The string S is never truncated.

性能

这也是最有效的替代方法:

>>> min(timeit.repeat(lambda: '1'.zfill(4)))0.18824880896136165>>> min(timeit.repeat(lambda: '1'.rjust(4, '0')))0.2104538488201797>>> min(timeit.repeat(lambda: f'{1:04}'))0.32585487607866526>>> min(timeit.repeat(lambda: '{:04}'.format(1)))0.34988890308886766

为了最好地比较%方法的苹果和苹果(注意它实际上更慢),否则会预先计算:

>>> min(timeit.repeat(lambda: '1'.zfill(0 or 4)))0.19728074967861176>>> min(timeit.repeat(lambda: '%04d' % (0 or 1)))0.2347015216946602

实施

通过一点挖掘,我在#1中找到了zfill方法的实现:

static PyObject *stringlib_zfill(PyObject *self, PyObject *args){Py_ssize_t fill;PyObject *s;char *p;Py_ssize_t width;
if (!PyArg_ParseTuple(args, "n:zfill", &width))return NULL;
if (STRINGLIB_LEN(self) >= width) {return return_self(self);}
fill = width - STRINGLIB_LEN(self);
s = pad(self, fill, 0, '0');
if (s == NULL)return NULL;
p = STRINGLIB_STR(s);if (p[fill] == '+' || p[fill] == '-') {/* move sign to beginning of string */p[0] = p[fill];p[fill] = '0';}
return s;}

让我们浏览一下这段C代码。

它首先在位置上解析参数,这意味着它不允许关键字参数:

>>> '1'.zfill(width=4)Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: zfill() takes no keyword arguments

然后检查它是否相同或更长,在这种情况下,它返回字符串。

>>> '1'.zfill(0)'1'

zfill调用pad(这个pad函数也被ljustrjustcenter调用)。这基本上是将内容复制到一个新字符串中并填充填充。

static inline PyObject *pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill){PyObject *u;
if (left < 0)left = 0;if (right < 0)right = 0;
if (left == 0 && right == 0) {return return_self(self);}
u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);if (u) {if (left)memset(STRINGLIB_STR(u), fill, left);memcpy(STRINGLIB_STR(u) + left,STRINGLIB_STR(self),STRINGLIB_LEN(self));if (right)memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),fill, right);}
return u;}

在调用pad之后,zfill将原来在+-之前的任何内容移动到字符串的开头。

请注意,原始字符串实际上不需要是数字:

>>> '+foo'.zfill(10)'+000000foo'>>> '-foo'.zfill(10)'-000000foo'

另一种方法是使用带有条件检查长度的列表理解。下面是一个演示:

# input list of strings that we want to prepend zerosIn [71]: list_of_str = ["101010", "10101010", "11110", "0000"]
# prepend zeros to make each string to length 8, if length of string is less than 8In [83]: ["0"*(8-len(s)) + s if len(s) < desired_len else s for s in list_of_str]Out[83]: ['00101010', '10101010', '00011110', '00000000']

使用Python>= 3.6时,最干净的方法是将f字串字符串格式一起使用:

>>> s = f"{1:08}"  # inline with int>>> s'00000001'
>>> s = f"{'1':0>8}"  # inline with str>>> s'00000001'
>>> n = 1>>> s = f"{n:08}"  # int variable>>> s'00000001'
>>> c = "1">>> s = f"{c:0>8}"  # str variable>>> s'00000001'

我更喜欢使用int格式化,因为只有这样才能正确处理符号:

>>> f"{-1:08}"'-0000001'
>>> f"{1:+08}"'+0000001'
>>> f"{'-1':0>8}"'000000-1'

它也ok:

 h = 2m = 7s = 3print("%02d:%02d:%02d" % (h, m, s))

所以输出将是:“02:07:03”

我做了一个函数:

def PadNumber(number, n_pad, add_prefix=None):number_str = str(number)paded_number = number_str.zfill(n_pad)if add_prefix:paded_number = add_prefix+paded_numberprint(paded_number)
PadNumber(99, 4)PadNumber(1011, 8, "b'")PadNumber('7BEF', 6, "#")

输出:

0099b'00001011#007BEF

我正在添加如何从f字符串中的字符串长度使用int,因为它似乎没有被覆盖:

>>> pad_number = len("this_string")11>>> s = f"{1:0{pad_number}}" }>>> s'00000000001'

对于数字:

i = 12print(f"{i:05d}")

产出

00012

如果您希望填充一个整数,并同时限制有效数字(使用f字符串):

a = 4.432>> 4.432a = f'{a:04.1f}'>> '04.4'

f'{a:04.1f}'这转换为1个小数/(浮点数)点,左填充数字直到总共4个字符。