简体   繁体   English

动态嵌套循环 - 泛化

[英]Dynamic Nested Loops - Generalization

Suppose I have the following 2 arbitrary classes:假设我有以下 2 个任意类:

class C1():
    def __init__(self, a):
        self.a = a
class C2():
    def __init__(self, a):
        self.a = a

And the following parameters:以及以下参数:

c1_args = [1, 2, 3, 4, 5]
c2_args = [1, 2, 3]

I want to run a function (let's call it do_something() ) n times, taking as arguments every possible pair of instances of (C1,C2) based on the parameters provided.我想运行一个函数(我们称之为do_something() )n 次,根据提供的参数将 (C1,C2) 的每个可能的实例对作为参数。 To do this, I created a nested loop, as shown below:为此,我创建了一个嵌套循环,如下所示:

for x in c1_args:
    c1_instance = C1(x)
    for y in c2_args:
        c2_instance = C2(y)
        do_something(c1_instance, c2_instance)

Now, I want to be able to generalize it for any number of classes (and parameters).现在,我希望能够将它概括为任意数量的类(和参数)。 For that, a simple - yet highly inefficient - way to do it would be to use itertools.product() , which I adapted from here :为此,一种简单但效率极低的方法是使用itertools.product() ,我从这里改编:

import itertools
def generalize(classes, args):
    combos = itertools.product(*args)
    for combo in combos:
        instances = [classes[i](args[i]) for i in range(len(combo))]
        do_something(instances)

This is highly inefficient because it must create the same instance multiple times - in my example above, C1(1) must be created 3 times, once for every C2 instance created.这是非常低效的,因为它必须多次创建相同的实例——在我上面的例子中,C1(1) 必须创建 3 次,每个 C2 实例创建一次。 That's irrelevant with the simple classes I provided above but with bigger classes it is heavily time consuming.这与我上面提供的简单类无关,但是对于更大的类,它非常耗时。

I suspect one solution would be recursion , based on what I found here .根据我在此处找到的内容,我怀疑一种解决方案是递归 Unfortunately I can't seem to make it work for my case (mostly due to my ignorance on recursion - apologies for that)不幸的是,我似乎无法让它适用于我的情况(主要是由于我对递归的无知 - 对此表示歉意)

If you create the instances first before looping throug the combinations, you can insure that the instances are only created once for each item in the lists:如果在遍历组合之前先创建实例,则可以确保为列表中的每个项目只创建一次实例:

from itertools import product

class C1():
    def __init__(self, a):
        print("making c1:", a)
        self.a = a
    def __repr__(self):
        return f"C1({self.a})"

class C2():
    def __init__(self, a):
        print("making c2:", a)
        self.a = a
        
    def __repr__(self):
        return f"C2({self.a})"

c1_args = map(C1, [1, 2, 3, 4, 5])
c2_args = map(C2, [1, 2, 3])


for comb in product(c1_args, c2_args):
    print(comb)

The prints show each __init__() being called once and then the various combinations:打印显示每个__init__()被调用一次,然后是各种组合:

making c1: 1
making c1: 2
making c1: 3
making c1: 4
making c1: 5
making c2: 1
making c2: 2
making c2: 3
(C1(1), C2(1))
(C1(1), C2(2))
(C1(1), C2(3))
(C1(2), C2(1))
(C1(2), C2(2))
(C1(2), C2(3))
(C1(3), C2(1))
(C1(3), C2(2))
(C1(3), C2(3))
(C1(4), C2(1))
(C1(4), C2(2))
(C1(4), C2(3))
(C1(5), C2(1))
(C1(5), C2(2))
(C1(5), C2(3))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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