while terminar for español ejemplos contador como ciclo bucle python python-2.7 batch-processing

terminar - for i in range python español



¿Cómo ejecutar un bucle for en lotes? (3)

La estructura general que uso se ve así:

worklist = [...] batchsize = 500 for i in xrange(0, len(worklist), batchsize): batch = worklist[i:i+batchsize] # the result might be shorter than batchsize at the end # do stuff with batch

Tenga en cuenta que estamos utilizando el argumento step de xrange para simplificar considerablemente el procesamiento por lotes.

for x in records: data = {} for y in sObjectName.describe()[''fields''] data[y[''name'']] = x[y[''name'']] ls.append(adapter.insert_posts(collection, data))

Quiero ejecutar el código ls.append (adapter.insert_post (collection, x)) en el tamaño de lote de 500, donde x debe contener 500 datos dicts. Podría crear una lista de 500 datos dicts utilizando un doble para bucle y una lista y luego insertarlo. Podría hacer eso de la siguiente manera, ¿hay una mejor manera de hacerlo? :

for x in records: for i in xrange(0,len(records)/500): for j in xrange(0,500): l=[] data = {} for y in sObjectName.describe()[''fields'']: data[y[''name'']] = x[y[''name'']] #print data #print data l.append(data) ls.append(adapter.insert_posts(collection, data)) for i in xrange(0,len(records)%500): l=[] data = {} for y in sObjectName.describe()[''fields'']: data[y[''name'']] = x[y[''name'']] #print data #print data l.append(data) ls.append(adapter.insert_posts(collection, data))


Si está trabajando con secuencias, la solución de @nneonneo es tan eficiente como pueda obtener. Si desea una solución que funcione con iterables arbitrarios, puede buscar algunas de las recetas itertools . por ejemplo, mero:

def grouper(iterable, n, fillvalue=None): "Collect data into fixed-length chunks or blocks" # grouper(''ABCDEFG'', 3, ''x'') --> ABC DEF Gxx args = [iter(iterable)] * n return itertools.izip_longest(fillvalue=fillvalue, *args)

Tiendo a no usar este porque "llena" el último grupo con None para que tenga la misma longitud que los otros. Normalmente defino mi propia variante que no tiene este comportamiento:

def grouper2(iterable, n): iterable = iter(iterable) while True: tup = tuple(itertools.islice(iterable, 0, n)) if tup: yield tup else: break

Esto produce tuplas del tamaño solicitado. En general, esto es lo suficientemente bueno, pero, por un poco de diversión, podemos escribir un generador que devuelva iteraciones perezosas del tamaño correcto si realmente queremos ...

La mejor solución aquí, creo, depende un poco del problema en cuestión, particularmente el tamaño de los grupos y objetos en el iterable original y el tipo del iterable original. Generalmente, estas dos últimas recetas encontrarán menos uso porque son más complejas y rara vez se necesitan. Sin embargo, si te sientes aventurero y de humor para divertirte un poco, ¡sigue leyendo!

La única modificación real que necesitamos para obtener un iterable perezoso en lugar de una tupla es la capacidad de "mirar" el siguiente valor en el islice para ver si hay algo allí. Aquí solo miro el valor - Si falta, StopIteration se StopIteration , lo que detendrá el generador como si hubiera terminado normalmente. Si está allí, lo itertools.chain usando itertools.chain :

def grouper3(iterable, n): iterable = iter(iterable) while True: group = itertools.islice(iterable, n) item = next(group) # raises StopIteration if the group doesn''t yield anything yield itertools.chain((item,), group)

Sin embargo, esta última función solo "funciona" si agotas completamente cada iterable cedido antes de pasar al siguiente. En el caso extremo de que no agote ninguno de los iterables, por ejemplo, list(grouper3(..., n)) , obtendrá "m" iterables que arrojan solo 1 ítem, no n (donde "m" es la "longitud" de la entrada iterable). Este comportamiento en realidad podría ser útil a veces, pero no típicamente. Podemos arreglar eso también si usamos la receta "consumir" itertools (que también requiere importar collections además de itertools ):

def grouper4(iterable, n): iterable = iter(iterable) group = [] while True: collections.deque(group, maxlen=0) # consume all of the last group group = itertools.islice(iterable, n) item = next(group) # raises StopIteration if the group doesn''t yield anything group = itertools.chain((item,), group) yield group

Por supuesto, list(grouper4(..., n)) arrojará iterables vacíos: cualquier valor que no se extraiga del "grupo" antes de la siguiente invocación del next (por ejemplo, cuando el ciclo for regresa al inicio) nunca se obtendrá cedido.


Tal vez algo como esto?

l = [] for ii, x in enumerate(records): data = {} for y in sObjectName.describe()[''fields''] data[y[''name'']] = x[y[''name'']] l.append(data) if not ii % 500: ls.append(adapter.insert_posts(collection, l)) l = []