Reputation: 55
My code contains multiple lines of a nested for loop . I wanted to try and reduce the amount of nested for loops being called by putting the code into its own function similar to the do_for_each
function below. Within the nested for loop I want to call another function. Below is a working example:
def do_for_each(self, func, h, w, init_data):
for x in range(1, h):
for y in range(1, w):
init_data[x,y] = func(x, y)
return init_data
def calculate_land_neighbours(self, x, y):
return self.lscape[x-1,y] + self.lscape[x+1,y] + self.lscape[x,y-1] + self.lscape[x,y+1]
ouput = self.do_for_each(self.calculate_land_neighbours, self.h+1, self.w+1, data)
However, my problem arises when the function called within do_for_each
does not take parameters x
or y
but another variable. For instance a new function would look like:
def add_to_density_array(self, seed):
if seed == 0:
return 0
else:
return random.uniform(0, 5.0)
output2 = self.do_for_each(self.add_to_density_array, self.h+1, self.w+1, data, seed)
For this to run properly I would need to amend my do_for_each
function to:
def do_for_each(self, func, h, w, init_data, seed):
for x in range(1, h):
for y in range(1, w):
init_data[x,y] = func(seed)
return init_data
Would anyone have any recommendations where I could keep the modularised code of the do_for_each
function but call functions within do_for_each
that do not have the same input parameters?
Upvotes: 0
Views: 223
Reputation: 1
You can try out Overloading Functions, here is a possible solution. You can read more here - https://www.geeksforgeeks.org/python-method-overloading/
def do_for_each(self, func, h, w, init_data, seed=None):
if seed==None:
for x in range(1, h):
for y in range(1, w):
init_data[x,y] = func(x, y)
return init_data
else:
for x in range(1, h):
for y in range(1, w):
init_data[x,y] = func(seed)
return init_data
Upvotes: 0
Reputation: 546035
Fundamentally, your two do_for_each
functions are just very different. They don’t really perform the same transformation at all — one changes matrix entries as a function of the x
, y
indices, and another doesn’t.
I would consider using a different abstraction here.
That said, you can make this work without changing the original do_for_each
: pass a lambda that wraps add_to_density_array
, instead of passing the latter directly:
add_to_density = lambda x, y: self.add_to_density_array(seed)
output2 = self.do_for_each(add_to_density, self.h+1, self.w+1, data)
Upvotes: 1
Reputation: 6298
You can use default parameter of seed
as None
and check if it exits and operate accordingly:
def do_for_each(self, func, h, w, init_data, seed=None):
for x in range(1, h):
for y in range(1, w):
# If no seed provided
if seed is None:
init_data[x, y] = func(x, y)
# Else, seed provided - use it
else:
init_data[x, y] = func(seed)
return init_data
This has the advantage of backward compatibility with the "old" do_for_each(self, func, h, w, init_data)
.
Upvotes: 0