str.zfill()
The .zfill() method pads a string on the left with zeros until it reaches the specified width. It’s particularly useful for formatting numbers, generating fixed-width identifiers, and ensuring consistent string lengths for display or processing.
Signature
str.zfill(width)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
width | int | — | The total width of the returned string. If the string is already longer than width, it’s returned unchanged. |
Return Value
Returns a new string of the specified width, padded with leading zeros. If the original string’s length equals or exceeds the width, a new string (identical to the original) is returned.
Examples
Basic Usage
>>> "42".zfill(4)
'0042'
>>> "hello".zfill(10)
'00000hello'
The method adds zeros to the left until the string reaches the target width. Strings shorter than the width get padded; strings equal to or longer than the width are returned as-is.
Number Formatting
>>> "7".zfill(3)
'007'
>>> "123".zfill(5)
'00123'
>>> "12345".zfill(3)
'12345' # No padding needed
This is the classic use case—formatting numbers with leading zeros, similar to what you might see in timestamps or invoice numbers.
Handling Negative Numbers
>>> "-42".zfill(5)
'-0042'
>>> "-3".zfill(4)
'-003'
.zfill() preserves the minus sign and pads after it. The total width includes the sign character.
Padding Hexadecimal and Other Bases
>>> hex(255)[2:].zfill(4)
'00ff'
>>> hex(4096)[2:].zfill(6)
'001000'
Combine with string slicing to pad hexadecimal representations.
Practical Use Cases
Generating sequential IDs:
for i in range(1, 11):
print(f"ID-{str(i).zfill(3)}")
# Output:
# ID-001
# ID-002
# ...
# ID-010
Formatting timestamps:
from datetime import datetime
now = datetime.now()
print(f"{now.hour.zfill(2)}:{now.minute.zfill(2)}")
# Output: "09:05" (for 9:05)
File naming with sequential numbers:
for i in range(100):
filename = f"data_{str(i).zfill(4)}.csv"
# Creates: data_0000.csv, data_0001.csv, ... data_0099.csv
Behavior Details
How It Works
The method calculates how many zeros to prepend by subtracting the current string length from the target width:
>>> s = "42"
>>> width = 4
>>> zeros_needed = width - len(s) # 4 - 2 = 2
>>> "0" * zeros_needed + s # "00" + "42" = "0042"
Sign Handling
The sign (if present) is preserved at the front, and zeros are inserted after it:
>>> "+42".zfill(5)
'+0042'
>>> "-42".zfill(5)
'-0042'
>>> "+0".zfill(3)
'+00'
Non-Numeric Strings
.zfill() works on any string, not just numbers:
>>> "abc".zfill(6)
'000abc'
>>> "".zfill(3)
'000'
>>> "test".zfill(0)
'test' # Width 0 returns original
Edge Cases
>>> "".zfill(0)
''
>>> "hello".zfill(-1)
'hello' # Negative width returns original (Python 3.11+)
>>> "001".zfill(3)
'001' # Already at width, no change
Common Mistakes
Assuming it works like rjust with ‘0’:
# zfill is equivalent to rjust with '0' for most cases:
>>> "42".zfill(4)
'0042'
>>> "42".rjust(4, '0')
'0042'
# But rjust can use any character:
>>> "42".rjust(4, 'x')
'xx42'
Forgetting about sign characters:
# The width includes the sign
>>> "-1".zfill(3) # width=3 gives '-01' (sign + 2 digits)
'-01'
>>> "-1".zfill(4) # width=4 gives '-001' (sign + 3 digits)
'-001'
Using with floats:
# zfill doesn't work directly on floats
>>> "3.14".zfill(6)
'03.14' # This works but may not be what you want
# For floats, convert to string first or use formatting:
>>> f"{3.14:05.2f}"
'03.14'
Performance
.zfill() creates a new string, so memory usage scales with the result size. It’s implemented in C and runs in O(n) time where n is the width. For most use cases with reasonable widths (under 1000 characters), performance is negligible.