join() в Python: как соединить список в строку
Метод join в Python: как превратить список в строку с разделителем, соединить числа через map(str), чем отличается os.path.join и почему join быстрее +=.
Содержание · 10 разделов
- Синтаксис str.join
- Python: список в строку
- Почему не str(list)
- Как соединить числа: map(str, …)
- join со словарями, строками и другими объектами
- join и split — обратные операции
- str.join, os.path.join и pathlib: в чём разница
- Производительность: join против += в цикле
- Частые ошибки
- TypeError: sequence item 0: expected str instance, int found
- AttributeError: ‘list’ object has no attribute ‘join’
- Разделитель в конце строки
- Вложенные списки
- Частые вопросы
- Как вывести список через пробел без скобок?
- Как объединить два списка?
- Как перечислить элементы через запятую и «и» перед последним?
- Можно ли соединить байты через join?
- Почему writelines() записал всё в одну строку?
- Итог
Метод join() в Python соединяет элементы списка (или любого итерируемого объекта) в одну строку. Короткий ответ: чтобы преобразовать список в строку, вызовите join у разделителя и передайте ему список — ", ".join(["a", "b", "c"]) вернёт 'a, b, c'.
Главное правило: все элементы должны быть строками. Ниже — как соединить список строк и список чисел, какие бывают разделители, чем str.join отличается от os.path.join и почему join быстрее склейки строк в цикле. Примеры проверены на Python 3.12.
Синтаксис str.join
разделитель.join(итерируемый_объект)
Метод принадлежит строке-разделителю, а не списку. Он проходит по элементам, вставляет разделитель между ними (не в начале и не в конце) и возвращает новую строку. Исходный список не меняется.
words = ["Python", "Django", "FastAPI"]
print(", ".join(words)) # → Python, Django, FastAPI
print(" ".join(words)) # → Python Django FastAPI
print("".join(words)) # → PythonDjangoFastAPI
print(" | ".join(words)) # → Python | Django | FastAPI
Если элемент один, разделитель не добавляется; для пустого списка результат — пустая строка ''.
print("-".join(["один"])) # → один
print(repr("-".join([]))) # → ''
Python: список в строку
Частые варианты разделителей:
lines = ["первая строка", "вторая строка"]
print("\n".join(lines))
первая строка
вторая строка
chars = ["P", "y", "t", "h", "o", "n"]
print("".join(chars)) # → Python
print("\t".join(["id", "name"])) # → id name
print(", ".join(f'"{w}"' for w in ["a", "b"])) # → "a", "b"
"\n".join(...) — стандартный способ собрать многострочный текст, например перед записью в файл. Пустой разделитель "" склеивает элементы вплотную.
Почему не str(list)
Функция str() тоже превращает список в строку, но вместе со скобками и кавычками — это представление для отладки, а не текст для пользователя:
items = ["яблоко", "груша"]
print(str(items)) # → ['яблоко', 'груша']
print(", ".join(items)) # → яблоко, груша
Как соединить числа: map(str, …)
join не преобразует типы сам. Список чисел приводит к ошибке:
nums = [1, 2, 3]
", ".join(nums) # → TypeError: sequence item 0: expected str instance, int found
Сначала превратите каждый элемент в строку — через map или генераторное выражение:
nums = [1, 2, 3]
print(", ".join(map(str, nums))) # → 1, 2, 3
print(" + ".join(str(n) for n in nums)) # → 1 + 2 + 3
print(" ".join(f"{n:02d}" for n in nums)) # → 01 02 03
Вариант с генератором удобен, когда числа нужно ещё и отформатировать. Генератор передаётся прямо в join, без лишних скобок.
join со словарями, строками и другими объектами
join принимает любой итерируемый объект со строковыми элементами:
config = {"host": "localhost", "port": "5432"}
print(", ".join(config)) # → host, port
print("; ".join(f"{k}={v}" for k, v in config.items())) # → host=localhost; port=5432
print("-".join("abc")) # → a-b-c
print(" ".join(("кортеж", "тоже", "можно"))) # → кортеж тоже можно
Словарь перебирается по ключам, поэтому join(config) соединяет только ключи. Строка перебирается по символам — так удобно вставить разделитель между буквами. Подробнее о словарях — в статье о dict в Python.
join и split — обратные операции
split делит строку на список, join собирает список в строку. Вместе они решают задачи вроде «заменить разделитель» или «нормализовать пробелы»:
date = "09.10.2026"
print("-".join(date.split(".")[::-1])) # → 2026-10-09
messy = " много лишних пробелов "
print(" ".join(messy.split())) # → много лишних пробелов
str.join, os.path.join и pathlib: в чём разница
У str.join и os.path.join похожее имя, но разная задача. os.path.join склеивает части пути и сам подставляет разделитель операционной системы:
import os
path = os.path.join("media", "uploads", "photo.jpg")
print(path)
# Windows: media\uploads\photo.jpg
# Linux и macOS: media/uploads/photo.jpg
Не собирайте пути через "/".join(...) или +: на Windows разделитель другой, а лишние или пропущенные слеши легко создают ошибки. Учтите и ловушку: если какая-то часть начинается со слеша, всё, что было до неё, отбрасывается — os.path.join("media", "/photo.jpg") вернёт '/photo.jpg'.
Современный способ работы с путями — модуль pathlib, где части соединяются оператором /:
from pathlib import Path
path = Path("media") / "uploads" / "photo.jpg"
print(path.name) # → photo.jpg
print(path.suffix) # → .jpg
print(path.as_posix()) # → media/uploads/photo.jpg
print(path) покажет путь с разделителем вашей ОС, а as_posix() всегда использует /.
Производительность: join против += в цикле
Строки в Python неизменяемы, поэтому каждая операция s = s + part создаёт новую строку и копирует в неё всё накопленное. join сначала вычисляет итоговую длину и собирает результат за один проход.
import timeit
parts = [str(i) for i in range(100_000)]
def concat():
s = ""
for p in parts:
s = s + p + ","
return s
def with_join():
return ",".join(parts)
print(concat() == with_join() + ",")
print(timeit.timeit(concat, number=1))
print(timeit.timeit(with_join, number=1))
Скрипт печатает True (результаты совпадают) и время каждого варианта в секундах. На тестовом компьютере редакции (Python 3.12.10, Windows 11, 100 000 элементов) склейка в цикле заняла около 4 секунд, а join — около 2–3 миллисекунд. На другом компьютере и в другой версии Python цифры будут другими. Запись вида s += p CPython в некоторых случаях оптимизирует: в том же замере цикл из s += p и s += "," занял около 30 миллисекунд. Но PEP 8 прямо советует не полагаться на эту оптимизацию и использовать "".join(). Правило простое: если строка собирается в цикле, копите части в список и соединяйте один раз в конце.
report = []
for name, score in [("Анна", 95), ("Иван", 88)]:
report.append(f"{name}: {score}")
print("\n".join(report))
Анна: 95
Иван: 88
Частые ошибки
TypeError: sequence item 0: expected str instance, int found
В списке есть не строка — число, None или другой объект. Номер в сообщении указывает на первый проблемный элемент. Решение — map(str, items) или генератор с str(). Если в данных встречается None, отфильтруйте его: ", ".join(x for x in items if x is not None).
AttributeError: ‘list’ object has no attribute ‘join’
words = ["a", "b"]
words.join(", ") # → AttributeError: 'list' object has no attribute 'join'
Порядок обратный: метод вызывается у разделителя — ", ".join(words). Как разбирать такие сообщения, описано в статье об ошибках и traceback.
Разделитель в конце строки
join не добавляет разделитель после последнего элемента. Если он всё же нужен (например, перевод строки в конце файла), добавьте его отдельно: "\n".join(lines) + "\n".
Вложенные списки
join работает только с одним уровнем. Список списков сначала разверните или соедините каждую строку отдельно:
table = [["a", "b"], ["c", "d"]]
print("\n".join(" ".join(row) for row in table))
a b
c d
Частые вопросы
Как вывести список через пробел без скобок?
Если строку нужно только напечатать, распакуйте список в print() звёздочкой. print() сам преобразует элементы в строки, поэтому map(str, ...) не нужен:
items = [1, 2, 3]
print(*items) # → 1 2 3
print(*items, sep=", ") # → 1, 2, 3
Для сохранения результата в переменную по-прежнему нужен join().
Как объединить два списка?
join() собирает строку, а для объединения списков используют + (новый список) или extend() (дописывает в существующий):
a = ["a", "b"]
b = ["c"]
print(a + b) # → ['a', 'b', 'c']
a.extend(b)
print(a) # → ['a', 'b', 'c']
Как перечислить элементы через запятую и «и» перед последним?
Соедините все элементы, кроме последнего, через запятую и добавьте последний отдельно. Список из одного элемента обработайте отдельно:
def human_join(words):
if len(words) < 2:
return "".join(words)
return ", ".join(words[:-1]) + " и " + words[-1]
print(human_join(["Python", "Django", "FastAPI"])) # → Python, Django и FastAPI
print(human_join(["Python"])) # → Python
Можно ли соединить байты через join?
Да, у bytes есть свой join(), но разделитель тоже должен быть байтовым: b"".join(chunks). Смешивать типы нельзя: "".join([b"a"]) вызовет TypeError: sequence item 0: expected str instance, bytes found.
chunks = [b"GET ", b"/ ", b"HTTP/1.1"]
print(b"".join(chunks)) # → b'GET / HTTP/1.1'
Почему writelines() записал всё в одну строку?
file.writelines(lines) записывает элементы подряд и не добавляет переводы строк. Соберите текст через join() и запишите одним вызовом: f.write("\n".join(lines) + "\n").
Итог
Чтобы превратить список в строку, вызывайте join у разделителя: ", ".join(items). Числа и другие объекты сначала преобразуйте в строки через map(str, ...), для путей используйте pathlib, а строки в циклах собирайте в список и соединяйте один раз. Больше приёмов работы с коллекциями — в статье о списках Python и в шпаргалке по синтаксису Python.
- #Python
- #join
- #Строки
- #Списки
- #Синтаксис