Tive um problema semelhante e encontrei a solução aqui . Funciona sem a necessidade de importar nenhum módulo.
Supondo uma lista como:
people = ["Lisa","Pam","Phil","John"]
Uma solução simplificada de uma linha ficaria assim.
Todos os pares possíveis , incluindo duplicatas:
result = [foo(p1, p2) for p1 in people for p2 in people]
Todos os pares possíveis, excluindo duplicatas :
result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2]
Pares únicos , onde a ordem é irrelevante:
result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]
Caso você não queira operar, mas apenas pegar os pares, foobastaria retirar a função e usar apenas uma tupla.
Todos os pares possíveis , incluindo duplicatas:
list_of_pairs = [(p1, p2) for p1 in people for p2 in people]
Resultado:
('Lisa', 'Lisa')
('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Pam')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'Phil')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')
('John', 'John')
Todos os pares possíveis, excluindo duplicatas :
list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2]
Resultado:
('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Lisa')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'Lisa')
('Phil', 'Pam')
('Phil', 'John')
('John', 'Lisa')
('John', 'Pam')
('John', 'Phil')
Pares únicos , onde a ordem é irrelevante:
list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]
Resultado:
('Lisa', 'Pam')
('Lisa', 'Phil')
('Lisa', 'John')
('Pam', 'Phil')
('Pam', 'John')
('Phil', 'John')
Edit: Após o retrabalho para simplificar esta solução, percebi que é a mesma abordagem que Adam Rosenfield. Espero que a explicação mais ampla ajude alguns a entendê-la melhor.