ZetCode

Python add strings

last modified October 30, 2026 Python 3.15

In this article we show how to concatenate strings in Python.

In Python, a string is an immutable sequence of Unicode characters. Adding strings never modifies an existing string; it always creates a new one.

There are several ways of adding strings in Python:

Python add strings with + operator

The easiest way of concatenating strings is to use the + operator. The + operator is used both for adding numbers and strings; in programming we say that the operator is overloaded.

plus_operator.py
a = 'old'
b = ' tree'

c = a + b
print(c)

Two strings are added using the + operator. The result is a new string; a and b are unchanged.

$ python plus_operator.py
old tree

Python add strings with += operator

The compound += operator appends a string to a variable. Since strings are immutable, the variable is rebound to a new string.

compound_add.py
msg = 'There are'

msg += ' three falcons'
msg += ' in the sky'

print(msg)

The example builds a message with the += operator.

$ python compound_add.py
There are three falcons in the sky

Adding strings and numbers

Python does not convert numbers to strings automatically. Adding a string and an integer raises a TypeError.

add_number.py
name = 'falcon'
n = 3

try:
    msg = 'There are ' + n + ' ' + name + 's'
except TypeError as e:
    print(e)

msg = 'There are ' + str(n) + ' ' + name + 's'
print(msg)

The first concatenation fails, because n is an integer.

msg = 'There are ' + str(n) + ' ' + name + 's'

We convert the number to a string with the built-in str function. String formatting, shown below, is usually more readable.

$ python add_number.py
can only concatenate str (not "int") to str
There are 3 falcons

Python add strings with join

The string join method concatenates any number of strings provided in an iterable, such as a list or a tuple. The string on which we call the method is the separator placed between the elements.

join_words.py
words = ['There', 'are', 'three', 'eagles', 'in', 'the', 'sky']

print(' '.join(words))
print('-'.join(words))
print(''.join(['a', 'b', 'c']))
print(', '.join(('falcon', 'eagle', 'hawk')))

In the example, we join seven words with a space and with a dash. An empty separator glues the strings together.

$ python join_words.py
There are three eagles in the sky
There-are-three-eagles-in-the-sky
abc
falcon, eagle, hawk

Joining non-string values

The join method accepts only strings. Other values must be converted first.

join_numbers.py
vals = [1, 2, 3, 4, 5]

try:
    print(', '.join(vals))
except TypeError as e:
    print(e)

print(', '.join(map(str, vals)))
print(' + '.join(str(val) for val in vals), '=', sum(vals))

Joining a list of integers raises a TypeError.

print(', '.join(map(str, vals)))

The map function applies str to each element. A generator expression does the same job in the next line.

$ python join_numbers.py
sequence item 0: expected str instance, int found
1, 2, 3, 4, 5
1 + 2 + 3 + 4 + 5 = 15

Python add strings with string formatting

We can build strings with string formatting. Python has f-strings, the format method, and the older % operator. Formatting converts values to strings automatically and can control their presentation.

format_str.py
w1 = 'two'
w2 = 'eagles'

msg = f'There are {w1} {w2} in the sky'
print(msg)

msg = 'There are {} {} in the sky'.format(w1, w2)
print(msg)

msg = 'There are %s %s in the sky' % (w1, w2)
print(msg)

n = 3
price = 12.5
print(f'{n} tickets cost {n * price:.2f} EUR')

We build the same message in three ways.

msg = f'There are {w1} {w2} in the sky'

In an f-string, the expressions inside the {} characters are evaluated and their values are inserted into the string.

print(f'{n} tickets cost {n * price:.2f} EUR')

The expression can be any Python expression, and a format specification follows the colon. Here we print the price with two decimal places. See Python f-string for details.

$ python format_str.py
There are two eagles in the sky
There are two eagles in the sky
There are two eagles in the sky
3 tickets cost 37.50 EUR

Adjacent string literals

String literals written next to each other are joined by the compiler. This is useful for splitting long strings across lines without the + operator.

literal_concat.py
msg = 'an old ' 'falcon'
print(msg)

query = ('SELECT name, occupation '
         'FROM users '
         'WHERE active = 1')
print(query)

langs = [
    'Python',
    'Ruby'
    'Perl',
    'Go',
]
print(langs)

The literals are joined at compile time, so this works only with literals, not with variables.

query = ('SELECT name, occupation '
         'FROM users '
         'WHERE active = 1')

Inside parentheses, the literals can span several lines.

langs = [
    'Python',
    'Ruby'
    'Perl',
    'Go',
]

The feature can also cause bugs. A missing comma after 'Ruby' silently joins two list items into one.

$ python literal_concat.py
an old falcon
SELECT name, occupation FROM users WHERE active = 1
['Python', 'RubyPerl', 'Go']

Repeating strings

The * operator repeats a string the given number of times.

repeat_str.py
print('-' * 20)
print('ab' * 3)

title = 'Report'
print(title)
print('=' * len(title))

We create separator lines. The underline under the title has the same length as the title.

$ python repeat_str.py
--------------------
ababab
Report
======

Python add strings with __add__ method

The + operator is implemented by the special __add__ dunder method. We can call it directly, although in practice we use the operator.

dunder_add.py
s1 = 'an old'
s2 = ' falcon'

s3 = s1.__add__(s2)
print(s3)

s4 = str.__add__(s1, s2)
print(s4)

The example adds two strings with __add__, called on the instance and on the str class.

$ python dunder_add.py
an old falcon
an old falcon

Performance of string concatenation

Since strings are immutable, each += in principle creates a new string and copies the old content. CPython optimizes += when no other reference to the string exists, but the join method remains the recommended way to build a string from many parts.

concat_perf.py
import timeit

words = ['falcon'] * 100_000


def plus_loop():
    res = ''
    for word in words:
        res += word + ' '
    return res


def join_list():
    return ' '.join(words) + ' '


def join_gen():
    return ''.join(word + ' ' for word in words)


assert plus_loop() == join_list() == join_gen()

for fn in (plus_loop, join_list, join_gen):
    t = timeit.timeit(fn, number=20) / 20
    print(f'{fn.__name__:10} {t * 1000:.2f} ms')

We build the same string from 100,000 words in three ways and measure the average time of twenty runs.

def join_list():
    return ' '.join(words) + ' '

Joining an existing list is the fastest, because join computes the final size first and copies each part once.

def join_gen():
    return ''.join(word + ' ' for word in words)

With a generator expression, join must first collect the parts into a list, and each word + ' ' creates a temporary string. On CPython, it is not faster than the += loop. Other Python implementations do not have the += optimization.

$ python concat_perf.py
plus_loop  5.67 ms
join_list  1.01 ms
join_gen   6.54 ms

Source

Python text sequence type - str

In this article we have shown several ways to add strings in Python.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.