Back to Blog
Python

Python String Repetition with the * Operator

python string repetition: How the * operator repeats strings in Python, covering multiplier edge cases, practical uses, memory cost, and when join or format is better.

pythonstring manipulationpython operatorsstring methodsmemory usagepython syntax
Editorial illustration showing a short text string repeated multiple times using the multiplication operator in Python

Python string repetition is the behavior that makes "ab" * 3 evaluate to "ababab". The * operator, normally associated with numeric multiplication, is overloaded for sequence types in Python. For strings, it repeats the entire sequence by the given integer count. This is one of the most direct ways to build repeated text without a loop.

The * Operator and Its Basic Behavior

When you write s * n, Python creates a new string containing s repeated n times:

separator = "-" * 40 print(separator) # ----------------------------------------

The operation is symmetric: n * s produces the same result as s * n. Both forms are valid, though s * n reads more naturally when the string is the subject of the operation.

The result is always a new string object. The original string is not modified, because strings are immutable in Python. Any repetition creates a fresh object in memory, which matters when the repeated string is large or the operation runs inside a hot loop.

How the Multiplier Is Interpreted

The multiplier must be an integer. Python accepts any object that implements __index__, which includes int and bool. Floats are rejected:

print("a" * 3) # aaa print("a" * 0) # (empty string) print("a" * -2) # (empty string) print("a" * True) # a

A multiplier of zero or any negative integer produces an empty string. This is not an error; it is the documented behavior for sequence repetition. A boolean multiplier works because True is 1 and False is 0 in Python's numeric model.

A float raises TypeError:

"a" * 2.5 # TypeError: can't multiply sequence by non-int of type 'float'

This is a common source of bugs when a count arrives from user input or an API response as a string or float. Converting the value with int() first, and validating that it is not negative, prevents surprising empty results.

Practical Uses for String Repetition

The most common uses are visual formatting and structural padding. Generating a horizontal rule in terminal output is a typical example:

width = 72 print("=" * width)

Repetition is also useful for building indentation, aligning columns in plain-text output, and creating simple progress bars:

def progress_bar(fraction, width=40): filled = int(fraction * width) bar = "#" * filled + "-" * (width - filled) return f"[{bar}] {fraction:.0%}"

Because the multiplier can be any integer expression, repetition composes well with len() and other calculations. The bar above uses two repetitions whose lengths sum to width, which keeps the total output length constant.

Memory and Runtime Cost of Repetition

String repetition allocates a new string whose length is len(s) * n. The runtime cost is proportional to the size of the output, because every character in the result must be written into the new buffer. For small strings and moderate multipliers this is negligible. For large strings or very large multipliers, the allocation can dominate.

A more subtle cost appears when repetition is combined with concatenation in a loop:

result = "" for i in range(n): result += "x"

Because strings are immutable, each += creates a new string and copies the entire accumulated content. This makes the loop quadratic in n. Replacing the loop with a single repetition is both faster and clearer:

result = "x" * n

The same principle applies when building repeated multi-character patterns. A single * operation is usually preferable to a loop that appends one copy at a time.

When to Prefer join or format Over Repetition

Repetition is the right tool when the output is exactly the same substring repeated. It is not the right tool when the repeated units need to be separated by a delimiter, or when each unit differs slightly.

For a comma-separated list of the same value, join is clearer:

", ".join(["item"] * 5) # item, item, item, item, item

Here ["item"] * 5 builds a list of five references to the same string, and join inserts the separator between them. The same result cannot be produced with a single * on a string, because that would place no separator between copies.

For padding with a specific alignment, str.ljust, str.rjust, and str.center already implement repetition internally. Using them avoids writing the padding logic yourself:

name = "report" print(name.ljust(20, ".")) # report..............

When the repeated text must be interpolated with other values, an f-string or format call is often more readable than concatenating several repetitions:

label = "status" line = f"{label}: {'=' * 10}"

Common Mistakes and Edge Cases

The most frequent mistake is passing a non-integer multiplier. A float count from len() / step or a string count from a JSON payload both raise TypeError. Convert and validate before repeating.

A second mistake is assuming that a negative multiplier raises an error. It silently produces an empty string, which can hide a bug where a count is computed incorrectly and the output disappears without an exception.

A third issue is memory exhaustion with an unvalidated multiplier. "x" * 10**9 attempts to allocate a one-gigabyte string. If the multiplier comes from external input, it should be bounded before the operation runs.

Compatibility Notes

String repetition works identically in Python 2 and Python 3 for both str and unicode/bytes types. The bytes type in Python 3 supports the same * operator and produces a repeated bytes object. Code that relies on repetition does not need version-specific branches, but code that mixes str and bytes still needs explicit conversion because the two types are distinct in Python 3.

The behavior of * on strings is part of the sequence protocol, shared with lists and tuples. A list multiplied by an integer repeats the references inside the list, which is why [[]] * 3 creates three references to the same inner list. Strings do not have this aliasing problem because they are immutable, but the shared protocol explains why the operator exists on all sequence types.

python string repetition: Practical Usage and Code Examples | RYUSLOG DEV