简体   繁体   中英

How to get rid of multiple nested loops in python

This is my code;

instance_count = 10
for imgs in wire_images:
    for counter in range(0, instance_count, 1):
        for oimgs in images_path:
            applyWireAugmentation(oimgs, imgs, wire_dir, odir, 0, dst_dir, counter, "waug")


def applyWireAugmentation(img, wire_img,wdir, odir, theata,dst_path, counter, index):

    src_im = Image.open(wdir+wire_img).convert("LA")
    dst_im = Image.open(odir+img)
    w,h = dst_im.size
    angle = theata
    size = 200, h

    x = random.randint(0,w)
    y = 0
    im = src_im.convert('RGBA')
    rot = im.rotate( angle, expand=1 ).resize(size)
    dst_im.paste( rot, (x, y), rot )
    dst_im.save(dst_path+"/"+img.replace(".png","")+"-"+index+"-"+str(counter)+".png")

wire_images has all the image files that are in a folder. images_path has all the images files in another folder. I need to take one image from wire_images apply it on oimgs instance_count times (10 in this case). Is there any sleek pythonic way to get rid of these loops or to make it faster?

You could generate all the possible combinations before, but I am not sure if it is better:

import itertools
comb = itertools.product(wire_images, images_path, range(0,instance_count,1))

for imgs, oimgs, counter in comb:
    applyWireAugmentation(oimgs, imgs,wire_dir,odir, 0, dst_dir, counter,  "waug")

itertools.product can be helpful here.

It can transform nested for loops to tuples which you can then use in your final statement.

You code will be like this:

from itertools import product   

for imgs, counter, oimgs in product(wire_images, range(0,instance_count,1), images_path):

    applyWireAugmentation(oimgs, imgs, wire_dir, odir, 0, dst_dir, counter, "waug")

Keep in mind that this for loop will not execute if any of the lists(iterators) are empty and it is a bit slower than nested for loop so you have to sacrifice performance a little bit in favor of readability.

Have a look at this Stackoverflow discussion for more info

As others suggested, one of the best possible way to achieve this is to use a generator which reduces the memory overhead drastically since there is no list to hold in-memory.

from itertools import product

wire_images = list1...  # if possible, try to get them in iterator format as well
images_path = list2...   # if possible, try to get them in iterator format as well
instance_count = 10

for imgs, oimgs, counter in product(wire_images, images_path, range(instance_count)):
    applyWireAugmentation(oimgs, imgs, wire_dir, odir, 0, dst_dir, counter, "waug")

The above approach has trade off of time over space and readability.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM