使用零填充数字字符串的最pythonic方法是什么,即数字字符串是否具有特定长度?
str.zfill 专门用于执行此操作:
>>> '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 field
of 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
实施
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 "", line 1, in
TypeError: zfill() takes no keyword arguments
然后检查它是否长度相同或更长,在这种情况下它返回字符串 .
>>> '1'.zfill(0)
'1'
zfill 调用 pad (此 pad 函数也由 ljust , rjust 和 center 调用) . 这基本上将内容复制到一个新字符串并填充填充 .
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'