如何批量执行for循环?

新手上路,请多包涵
for x in records:
   data = {}
   for y in sObjectName.describe()['fields']
         data[y['name']] = x[y['name']]
   ls.append(adapter.insert_posts(collection, data))

我想以 500 的批量大小执行代码 ls.append(adapter.insert_post(collection, x)),其中 x 应包含 500 个数据指令。我可以使用双 for 循环和一个列表创建一个包含 500 个数据字典的列表,然后将其插入。我可以通过以下方式做到这一点,有更好的方法吗? :

 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))

原文由 Mudits 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 668
2 个回答

我使用的一般结构如下所示:

 worklist = [...]
batchsize = 500

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

请注意,我们正在使用 step 参数 range 来大大简化批处理。

原文由 nneonneo 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您正在处理序列,@nneonneo 的解决方案将尽可能高效。如果你想要一个适用于任意迭代的解决方案,你可以查看一些 itertools 食谱。例如石斑鱼:

 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)

我倾向于不使用这个,因为它用 None “填充”最后一组,因此它的长度与其他组相同。我通常定义自己的变体,它没有这种行为:

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

这会产生请求大小的元组。这通常已经足够好了,但是,为了一点乐趣,我们可以编写一个生成器,如果我们真的想……

我认为此处的“最佳”解决方案在一定程度上取决于手头的问题——尤其是原始可迭代对象中组和对象的大小以及原始可迭代对象的类型。通常,最后这 2 个食谱会发现用处较少,因为它们更复杂且很少需要。但是,如果您喜欢冒险并想找点乐子,请继续阅读!


我们需要获得惰性迭代而不是元组的唯一真正修改是能够“查看” islice 中的下一个值,看看那里是否有任何东西。在这里,我只是查看值 -- 如果它丢失了, StopIteration 将被提升,这将停止生成器,就像它正常结束一样。如果它在那里,我使用 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)

不过要小心,如果你在继续下一个迭代 之前 完全耗尽每个 iterable yielded,最后一个函数 _只会_“起作用”。在极端情况下,您没有用尽任何可迭代对象,例如 list(grouper3(..., n)) ,您将得到“m”可迭代对象,它只产生 1 个项目,而不是 n (其中“m “是输入迭代的“长度”)。这种行为有时实际上很有用,但通常不是。如果我们使用 itertools“消费”配方,我们也可以解决这个问题(除了 — 之外,还需要导入 collections 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

当然, list(grouper4(..., n)) 将返回空的可迭代对象——在下一次调用 next 之前没有从“组”中提取的任何值(例如,当 for 回到起点)永远不会屈服。

原文由 mgilson 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题