Generate Letter Combinations of a Phone Number The task: Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.

and my solution:

import itertools
letters_stack = list('abcdefghijklmnopqrstuvwxyz')
keypad_dict = {}
for num in range(2, 10):
    size = 3
    if num in [7, 9]:
        size = 4
    keypad_dict[str(num)] = letters_stack[:size]
    letters_stack = letters_stack[size:]

def aux(numbers):
    if len(numbers) == 1:
        return keypad_dict[numbers[0]]
    return itertools.product(keypad_dict[numbers[0]],  iletters(numbers[1:]))    

def iletters(numbers):
    assert len(numbers) &gt; 0
    return [''.join(x) for x in aux(numbers)]



print list(iletters('234'))
# ['adg', 'adh', 'adi', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'bdg', 'bdh', 'bdi', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'cdg', 'cdh', 'cdi', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi']
You can set the keypad lookup as a constant instead of computing it dynamically. Setting it up as constant makes it clearer that what your intent is.

KEYPAD = {
    '2': 'abc',
    '3': 'def',
    '4': 'ghi',
    '5': 'jkl',
    '6': 'mno',
    '7': 'pqrs',
    '8': 'tuv',
    '9': 'wxyz'}




itertools.product can accept multiple lists. And in python, you can use * to unpack an iterable into positional arguments, and ** to unpack as keyword arguments.

To sum up:

def t9_mode(numbers):
    if len(numbers) == 1:
        return KEYPAD[numbers[0]]
    maps = map(KEYPAD.get, numbers)
    return [''.join(_) for _ in itertools.product(*maps)]


does the job.