Quick answer: Use itertools.permutations(iterable, r) to lazily produce ordered r-length arrangements without repeating an input position. The output count is factorial, so choose r and the input size with the result volume in mind.

A permutation is an ordered arrangement of items. If the items are A, B, and C, then ABC and BAC are different permutations because the order changed. In Python, the usual tool is itertools.permutations(), which returns tuples in the order they are generated.
The Python itertools permutations documentation describes the function as producing successive r-length permutations from an iterable. If r is omitted, Python uses the full length of the input. For random reordering instead of all ordered arrangements, see the NumPy random permutation guide.
Permutation counts can grow quickly. A list of three distinct items has six full-length permutations, but a list of ten distinct items has millions. Generate only the length you need and avoid converting huge permutation iterators into lists unless the result is intentionally small.
The most important rule is that permutations care about order. If order does not matter, you probably want combinations instead. If random order is enough, use a shuffle or random permutation. Use itertools.permutations() when you need to examine every ordered arrangement.
Generate Permutations Of A List
Pass a list and the desired length to permutations(). This example produces ordered pairs from three numbers.
from itertools import permutations
numbers = [1, 2, 3]
pairs = permutations(numbers, 2)
for pair in pairs:
print(pair)
The result contains tuples such as (1, 2) and (2, 1). Both appear because order matters in permutations.
The second argument controls the length of each arrangement, not the number of results. With three input items and length two, Python produces every ordered pair that can be made without reusing the same input position.
Use The Full Input Length
When the second argument is omitted, Python uses the full input length. For three distinct numbers, that gives six arrangements.
from itertools import permutations
numbers = [1, 2, 3]
all_orders = list(permutations(numbers))
print(all_orders)
Converting to a list is fine for small examples. For larger inputs, iterate over the permutation object directly so Python does not have to store every result at once.
The object returned by permutations() is an iterator. Once it has been consumed by a loop or list conversion, create a new iterator if you need to read the arrangements again.

Permute Characters In A String
Strings are iterable, so permutations() works on characters. Join each tuple of characters when you want strings instead of tuples.
from itertools import permutations
letters = "ABC"
words = ["".join(chars) for chars in permutations(letters)]
print(words)
If you need lexicographic order, sort the input first. That gives predictable output when the input characters are not already ordered. For related string handling, see the Python lowercase guide.
Joining character tuples is a common step because permutations("ABC") returns tuples like ("A", "B", "C"). The join step turns each tuple back into a normal string.
Count Permutations Without Generating Them
Use math.perm() when you only need the count. It avoids building every arrangement. The Python math.perm documentation covers the count formula.
from math import perm
items = 4
chosen = 2
print(perm(items, chosen))
print(perm(items))
The first call counts ordered pairs from four items. The second call counts all full-length arrangements. Counting first helps you decide whether generating the actual permutations is practical.
This is especially helpful for user-facing tools. If the count is huge, show a warning, require a smaller length, or stream a limited number of results instead of trying to display everything.

Handle Duplicate Input Values
itertools.permutations() treats positions as unique, not values. If the input has repeated values, duplicate tuples can appear. Use a set when you need unique arrangements.
from itertools import permutations
letters = "AAB"
unique_orders = sorted({"".join(chars) for chars in permutations(letters)})
print(unique_orders)
This removes duplicate output after generation. For large inputs with many duplicates, a custom generator can be more efficient, but the set approach is simple and readable for small cases.
Duplicate input values are common in strings and lists. Decide whether duplicate arrangements are meaningful for your problem before removing them.

Write A Recursive Permutation Function
You can also write permutations manually to understand the algorithm. The function below chooses one item as the first item and recursively permutes the remaining items.
def recursive_permutations(items):
if len(items) <= 1:
return [items]
results = []
for index, item in enumerate(items):
rest = items[:index] + items[index + 1:]
for order in recursive_permutations(rest):
results.append([item] + order)
return results
print(recursive_permutations([1, 2, 3]))
The built-in itertools version is better for production code because it is implemented efficiently and returns an iterator. The recursive version is useful for learning and for small custom cases.
A recursive implementation also makes the idea visible: pick a first item, permute what remains, then combine the first item with each smaller result.
Use itertools.permutations() when you need ordered arrangements, math.perm() when you only need the count, and a set when repeated input values create duplicate outputs. Keep input sizes small or stream the iterator, because permutation counts grow very quickly.
Understand The Permutation Count
permutations() treats each input position as unique. For n input positions and length r, the number of tuples is n! / (n - r)!. When r is omitted, it defaults to the full input length. A lazy iterator avoids building every result at once, but it cannot make a factorial number of results cheap to consume.
from itertools import permutations
letters = "ABC"
for item in permutations(letters, 2):
print("".join(item))

Permutations Versus Combinations
Use permutations when order matters: (A, B) and (B, A) are different. Use itertools.combinations() when the same selected positions should appear only once regardless of order. Use product() when positions may reuse values and the Cartesian product is the intended model.
Handle Duplicate Values And Large Results
Repeated values in the input can produce repeated value tuples because uniqueness is based on position, not value. If the application needs unique value arrangements, normalize or deduplicate deliberately. For large inputs, stream the iterator into a bounded consumer, stop early, or use a different algorithm instead of converting every result to a list.
Frequently Asked Questions
How do I generate permutations in Python?
Use itertools.permutations(iterable, r) to produce successive r-length tuples of ordered arrangements.
What is the difference between permutations and combinations?
Permutations treat different orders as different results, while combinations select the same positions without treating order as significant.
How many permutations are generated?
For n input positions and length r, permutations produces n! / (n-r)! tuples; if r is omitted, r defaults to n.
Does itertools.permutations remove duplicate values?
No. Elements are unique by input position, so repeated input values can produce repeated value tuples unless you normalize or deduplicate them.