¿Cómo crear un iterador infinito para generar un patrón alfabético creciente?

He creado una función que genera una lista de alfabetos que se incrementan continuamente. A, B, C …, Z. Después de Z, va a AA, AB, AC … AZ. Este patrón se repite. Esto es similar a los nombres de columna de MS Excel. En este momento, esta función genera una lista finita de alfabetos.

_column_name_generator() = ['A', 'B', ..., 'AA', 'AB', ..., 'BA', 'BB', ..., 'CV'] 

Luego puedo iterar sobre él junto con una lista finita, por ejemplo, 0-10. Ver mi código a continuación. Lo que me gustaría es crear un generador que me dé una lista infinitamente larga de alfabetos en aumento.

 import string def _column_name_generator(): column_names = [] for x in range(0, 100): if x < 26: column_names.append(string.ascii_uppercase[x % 26]) else: column_names.append(column_names[x/26 - 1] + string.ascii_uppercase[x % 26]) return column_names container = [] for column_name, num in zip(_column_name_generator(), range(0, 10)): container.append(column_name + str(num)) print _column_name_generator() print container container = ['A0', 'B1', 'C2', 'D3', 'E4', 'F5', 'G6', 'H7', 'I8', 'J9'] 

column_names el último elemento de itertools.count cada vez, y use itertools.count lugar de range para proporcionar un aumento infinito:

 import itertools def _column_name_generator(): column_names = [] for x in itertools.count(): if x < 26: column_names.append(string.ascii_uppercase[x % 26]) else: column_names.append(column_names[x/26 - 1] + string.ascii_uppercase[x % 26]) yield column_names[-1] 

Una solución mejor, alterando el código original pero descartando la necesidad en una lista de nombres de column_names consumen memoria, sería

 import itertools, string def _column_name_generator(): for i in itertools.count(1): for p in itertools.product(string.ascii_uppercase, repeat=i): yield ''.join(p) 

básicamente itera sobre el producto de longitud i las letras mayúsculas en mayúsculas (cada secuencia posible) cuando i está aumentando gradualmente, comenzando desde 1 ( A , B , C ).

Una forma menos pythonica.

Como está implícito en su pregunta, una forma es dividir por 26 convirtiendo el rest en una letra en cada paso, hasta que la división devuelva 0. Use % (módulo) para obtener el rest, // (división de piso) para actualizar el valor de próximo paso. Este podría ser el código:

 numberOfElements = 100 letters = [] for counter in range(numberOfElements): i = counter newCharacter = i % 26 i //= 26 s = "" +chr(newCharacter + ord('A') ) while i != 0: newCharacter = i % 26 i //= 26 s = chr(newCharacter + ord('A') ) + s letters.append(s) print letters 

Resultado:

[‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘ M ‘,’ N ‘,’ O ‘,’ P ‘,’ Q ‘,’ R ‘,’ S ‘,’ T ‘,’ U ‘,’ V ‘,’ W ‘,’ X ‘,’ Y ‘ , ‘Z’, ‘BA’, ‘BB’, ‘BC’, ‘BD’, ‘BE’, ‘BF’, ‘BG’, ‘BH’, ‘BI’, ‘BJ’, ‘BK’, ‘ BL ‘,’ BM ‘,’ BN ‘,’ BO ‘,’ BP ‘,’ BQ ‘,’ BR ‘,’ BS ‘,’ BT ‘,’ BU ‘,’ BV ‘,’ BW ‘,’ BX ‘ , ‘BY’, ‘BZ’, ‘CA’, ‘CB’, ‘CC’, ‘CD’, ‘CE’, ‘CF’, ‘CG’, ‘CH’, ‘CI’, ‘CJ’, ‘ CK ‘,’ CL ‘,’ CM ‘,’ CN ‘,’ CO ‘,’ CP ‘,’ CQ ‘,’ CR ‘,’ CS ‘,’ CT ‘,’ CU ‘,’ CV ‘,’ CW ‘ , ‘CX’, ‘CY’, ‘CZ’, ‘DA’, ‘DB’, ‘DC’, ‘DD’, ‘DE’, ‘DF’, ‘DG’, ‘DH’, ‘DI’, ‘ DJ ‘,’ DK ‘,’ DL ‘,’ DM ‘,’ DN ‘,’ DO ‘,’ DP ‘,’ DQ ‘,’ DR ‘,’ DS ‘,’ DT ‘,’ DU ‘,’ DV ‘ ]