Nicest way to pad zeroes to a string
最简单的填充方法是什么?左边是零的数字字符串,也就是说,数字字符串有一个特定的长度?
串:
1 2 3 | >>> n = '4' >>> print(n.zfill(3)) 004 |
对于数字:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> n = 4 >>> print('%03d' % n) 004 >>> print(format(n, '03')) # python >= 2.6 004 >>> print('{0:03d}'.format(n)) # python >= 2.6 004 >>> print('{foo:03d}'.format(foo=n)) # python >= 2.6 004 >>> print('{:03d}'.format(n)) # python >= 2.7 + python3 004 >>> print('{0:03d}'.format(n)) # python 3 004 >>> print(f'{n:03}') # python >= 3.6 004 |
字符串格式文档。
只需使用字符串对象的rjust方法。
此示例将生成一个长度为10个字符的字符串,并根据需要填充。
1 2 3 | >>> t = 'test' >>> t.rjust(10, '0') >>> '000000test' |
数字:
1 | print"%05d" % number |
另请参见:python:string格式。
编辑:值得注意的是,截止到2008年12月3日昨天,这种格式化方法已被弃用,取而代之的是
1 2 | print("{0:05d}".format(number)) # or print(format(number,"05d")) |
详见PEP 3101。
1 2 3 4 | >>> '99'.zfill(5) '00099' >>> '99'.rjust(5,'0') '00099' |
如果你想要相反的:
1 2 | >>> '99'.ljust(5,'0') '99000' |
同时在python 2和python 3中工作:
1 2 3 4 | >>>"{:0>2}".format("1") # Works for both numbers and strings. '01' >>>"{:02}".format(1) # Only works for numbers. '01' |
1 2 3 4 5 6 7 8 9 | >>> n = 3 >>> str(n).zfill(5) '00003' >>> n = '3' >>> str(n).zfill(5) '00003' >>> n = '3.0' >>> str(n).zfill(5) '003.0' |
对于那些来这里理解的人来说,不仅仅是一个简单的回答。我做这些特别是为了时间字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 | hour = 4 minute = 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" symbols what to replace with the"2" padding characters, the default is an empty space
">" symbols allign all the 2"0" character to the left of the string
":" symbols the format_spec
1 2 3 4 | width = 10 x = 5 print"%0*d" % (width, x) > 0000000005 |
有关所有令人兴奋的详细信息,请参阅打印文档!
更新python 3.x(7.5年后)
最后一行应该是:
1 | print("%0*d" % (width, x)) |
也就是说,
What is the most pythonic way to pad a numeric string with zeroes to the left, i.e., so the numeric string has a specific length?
1 2 | >>> '1'.zfill(4) '0001' |
注意,它专门用于按要求处理数字字符串,并将
1 2 3 4 | >>> '+1'.zfill(4) '+001' >>> '-1'.zfill(4) '-001' |
这是关于EDOCX1的帮助(9):
1 2 3 4 5 6 7 8 | >>> 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 field of the specified width. The string S is never truncated. |
性能
这也是最有效的替代方法:
1 2 3 4 5 6 7 8 | >>> 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 |
为了最好地比较
1 2 3 4 | >>> min(timeit.repeat(lambda: '1'.zfill(0 or 4))) 0.19728074967861176 >>> min(timeit.repeat(lambda: '%04d' % (0 or 1))) 0.2347015216946602 |
实施
经过一番挖掘,我发现了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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 2 3 4 | >>> '1'.zfill(width=4) Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: zfill() takes no keyword arguments |
然后检查长度是否相同或更长,在这种情况下,它返回字符串。
1 2 | >>> '1'.zfill(0) '1' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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; } |
在调用
请注意,对于原始字符串,不需要实际为数字:
1 2 3 4 | >>> '+foo'.zfill(10) '+000000foo' >>> '-foo'.zfill(10) '-000000foo' |
1 2 3 4 | >>> width = 4 >>> x = 5 >>> print("%0*d" %(width,x)) >>> 00005 |
这将在python 3.x中工作
对于保存为整数的邮政编码:
1 2 3 4 5 6 | >>> a = 6340 >>> b = 90210 >>> print '%05d' % a 06340 >>> print '%05d' % b 90210 |
快速定时比较:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | setup = ''' from random import randint def 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 timeit print 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] |
我对不同的重复做了不同的测试。差异不大,但在所有测试中,
您还可以重复"0",将其预先发送到
1 2 | def pad_left(n, width, pad="0"): return ((pad * width) + str(n))[-width:] |