Pregunta

I want to make a lot of functions based off of where I am in a loop. For example:

k=0    
for i in range(1,64):
    for j in range (1,64):
        for h in range(1,65-i):
            for w in range(1,(65-j)/2):
               k = k+1
               def make_feature+str(k)(imgmat, i, j, h, w):

Is something like this possible? I need a a lot of functions like this.

¿Fue útil?

Solución

What it looks like you're trying to do is create functions with pre-assigned values for i, j, k, andw. That is, you don't want to pass those values in, you want the function to know them already, and for them to be different based on which exact function you call.

There is almost no point to this, you're almost always better off just calling the function and passing in the values, but it can be done.

First we'll need a function that makes the desired function and "bakes in" the predefined variables. Since you're new to Python I won't go into the details of why, I'll just point out that we need it. (You could also use functools.partial or default argument values.)

def make_make_feature(i, j, k, w):

    def make_feature(imagemat):
        # do whatever make_feature does
        # using imagemat, i, j, k, and w

    return make_feature

What we have here is a function, make_make_feature(), that takes the four arguments, and returns a function (make_feature()) that takes a single argument and can use the variables as they were passed to the "maker" function. imgmat must be passed to the constructed function when it is later called but it already knows the other four values.

Now we have the nested loops that define the functions. We'll store them in a dictionary; the key will be a tuple of the four arguments.

make_feature_funcs = {}

for i in range(1, 64):
    for j in range (1, 64):
        for h in range(1, 65 - i):
            for w in range(1, (65 - j) / 2):
                 make_feature_funcs[i, j, k, w] = make_make_feature(i, j, k, w)

Now we have the dictionary make_feature_funcs. So, make_feature_funcs[1, 2, 3, 4] is the function that has the values 1, 2, 3, and 4 baked in for the variables i, j, k, and w. We can then call that function and pass in imgmat:

 make_feature_funcs[1, 2, 3, 4](imgmat)

As you can see this is no clearer than just calling make_feature() directly and passing in the variables you want.

One (minor) advantage is that you can only use the pre-defined values for i, j, k, and w, but you could also just add code to the function to validate the values if that's your goal. Which is why I said that there's almost no point in doing it.

Otros consejos

Instead of making different functions, you could create a class and just instatiate the class and call the function each time. Alternatively you could make the init function take the arguments.

class foo():
  def make_features(self,h,i,j,k,w):
    blah


   k=0    
for i in range(1,64):
    for j in range (1,64):
        for h in range(1,65-i):
            for w in range(1,(65-j)/2):
               k = k+1
               item = foo()
               item.make_features(h,i,j,k,w)

In general it is better to use a dictionary instead of dynamically creating variable names (including function names). You end up with similar behavior where you can perform a lookup based on the dynamic part of the name, but using a dictionary rather than the current scope is considered cleaner.

Here is how this might look:

make_feature = {}
k=0    
for i in range(1,64):
    for j in range (1,64):
        for h in range(1,65-i):
            for w in range(1,(65-j)/2):
               k = k+1
               def func(imgmat, i=i, j=j, h=h, w=w):
                   # do something
                   pass
               func.__name__ = 'make_feature' + str(k)
               make_feature[k] = func

After this you would be able to call a function like make_feature[1](...) and it would be essentially the same thing as what make_feature1(...) would have done if you used your current approach.

Note that I also used default values in the function definition to bind the current values of those variables to each function you create, since it seems like that may be what you want to do.

Although I am really wondering if it is actually necessary for you to create these multiple functions inside of the loop, but there isn't enough information from your question on what you are actually doing to suggest an alternative.

You could call make_feature separately for all of the values of h, i, j, k, and w. For example, this could look like....

def make_feature(imgmat, i, j, h, w): 
    #Compute Sum of Pixels in [i,i+h-1] x [j,j+w-1]
    S1=imgmat

    #Compute Sum of Pixels in [i,i+h-1] x [j,j+w-1]
    S2= something

    #Record this feature parameterized by (1,i,j,w,h) 
    return(S1 - S2)

for i in range(1,64):
    for j in range (1,64):
        for h in range(1,65-i):
            for w in range(1,(65-j)/2):
                make_feature(imgmat, i, j, h, w)    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top