Some optimizations on the suggestion by @Eastsun are:
Use a single mutable list
to store each permutation. This is faster than repeatedly copying immutable strings as a result of the '+' operator, even when converting the list to string at the end.
Swap values in the items
list to avoid expensive items[:i]+items[i+1:]
copies with O(n) complexity, and then an undo-swap is required when backtracking.
from typing import Iterator
def permutations(items: str) -> Iterator[list[str]]:
yield from _permutations_rec(list(items), 0)
def _permutations_rec(items: list[str], index: int) -> Iterator[list[str]]:
if index == len(items):
yield items
else:
for i in range(index, len(items)):
items[index], items[i] = items[i], items[index] # swap
yield from _permutations_rec(items, index + 1)
items[index], items[i] = items[i], items[index] # backtrack
# print permutations
for x in permutations('abc'):
print(''.join(x))