2

I think my question should be more clearly understood by this short code:

fs = []
for k in range(0, 10):
    def f(x):
        return x + 2*k
    fs.append(f)
fs[0](1)
# expecting 1 but 19(=1+2*9)

How do I instead make f return what I want? Please note that f cannot receive k as an argument.

(What I'm actually trying to do is prepare multiple constraint functions that are fed to scipy.optimize.minimize)

1

2 Answers 2

5

The typical way to fix this is to do something like:

def f(x, k=k):
    return x + 2*k

For the most part, this shouldn't affect your "f cannot receive k as an argument" condition because it isn't a required argument.


A related, but different approach would be to define f out of the loop.

def f(k, x):
    return x + 2*k

Then in the loop use functools.partial.

import functools
fs = []
for k in range(10):
    fs.append(functools.partial(f, k))

In this approach, your function won't accept a value for k even if you try to pass one.

Sign up to request clarification or add additional context in comments.

Comments

2

Basically the problem is that the variable k, in this case, continually changes as the loop iterates. This means that all things which are pointing to the variable "k" are pointing to the same value at all times.

There are a couple of ways to solve this. This is perhaps the most common.

def f(x, k=k):
   # This sets k as a locally bound variable which is evaluated
   # at the time the function is created.
   return x + 2*k

The detriment is that this solution will allow a later function to call the newly created functions with a different value of k. This means you could call f("cat","dog") and get "catdogdog" as a return. While this is not the end of the world, it certainly isn't intended.

However, you could also do something like this:

def f_maker(k):
   # Create a new function whose variable "k" does not exist in outside scope.
   def f(x):
       return x + 2*k
   return f

fs = []
for k in range(0, 10):
   fs.append(f_maker(k))

fs[0](1)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.