-2

I'm trying to define a function of 3 unknown variables (k,m,c) but let's say I have to define it 100 times due to a different frequency f each time. Can I do this in a for loop in python and store all the functions in a list such that they are callable later?

This is what I have so far

index = -1
f_t = []
for f in inputs[:,0]:
   index = index +1
   def F_analytic(k, m, c):
      F_t = k*m*c*f 
      return F_t
   f_t.append([])
   f_t[index].append(F_analytic)

but what I get in turn is a list of functions which are not callable:

Out[58]: 
[[<function __main__.F_analytic>],
[<function __main__.F_analytic>],
[<function __main__.F_analytic>],
[<function __main__.F_analytic>],
[<function __main__.F_analytic>],
...
... 
[<function __main__.F_analytic>],
[<function __main__.F_analytic>],
[<function __main__.F_analytic>]]

and the error is:

TypeError: 'list' object is not callable

Any help? Thank you!

S88S
  • 127
  • 1
  • 2
  • 6
  • 1
    Wait. You want to call a function with different parameters each time, but still can's see why do you want to define a function 100 times – matcheek Sep 20 '13 at 11:21
  • Why not make `f` a parameter as well to your function? –  Sep 20 '13 at 11:22
  • ...and if you insist on having gazillion functions, see [`functools.partial`](http://docs.python.org/2/library/functools.html#functools.partial) – Kimvais Sep 20 '13 at 11:24
  • Well the above is an extract of a rather complicate optimization process wherwe I have a constant value that is obtained from 100 different inputs of f. The function that I have to optimize also changes for every f. This is why I'm using this approach. – S88S Sep 23 '13 at 12:30
  • The functions are perfectly callable (although they might not due what you expect, due to late binding). The problem is that they are put into a list of lists, rather than a simple list. The exception comes from incorrect code to access the contents, not from the function object itself. This should have just been closed as a typo; and this is a good example of why [mre]s and [debugging](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) are important. – Karl Knechtel Aug 16 '22 at 00:21

5 Answers5

2

No, what you have is a list of lists of functions, with each inner list having 1 function.

Replace

f_t.append([])
f_t[index].append(F_analytic)

with

f_t.append(F_analytic)

(Although honestly, this whole approach seems rather suspicious; any reason you don't want one function with 4 parameters instead of 100 with 3?)

Wooble
  • 87,717
  • 12
  • 108
  • 131
1

① You are nesting lists although you just want a flat list (of functions). See the answer of @BartoszKP on that.

② You want to create functions based on local variables. You can do this using lambdas, as @Harsh is proposing, or you can do it using defaulted variables:

def F_analytic(k, m, c, f=f):  # notice the f=f here!
    F_t = k*m*c*f 
    return F_t

③ You should consider whether having a list of functions really is what you want (as @Wooble already pointed out).

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • Thank you! As of now, a list of functions is what I want! because what I have to optimize later is the sum of the square of the differences between the function (that changes with f) and a constant value (which is different for each f)! – S88S Sep 23 '13 at 12:34
0

This is because you are creating a list of lists, you can call each function object like this:

f_t[0][0](1,2,3)

Alternatively, just create a list of functions:

f_t = []

for f in inputs[:,0]:
    index = index +1
    def F_analytic(k, m, c):
        F_t = k*m*c*f 
        return F_t
    f_t.append(F_analytic)

And as noted by other answers and comments, this all seems a rather strange approach. Do you really need to do this? :)

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
-1

Sorry i dont think i answered the question properly, try this approach:

f_t = []
for f in input[:,0]:
    f_t.append(lambda k, m, c: k*m*c*f)

You can call the functions easily by: lets say you want to call the first one:

f_t[0](k,m,c)

Where k,m,c are your variables

Harsh
  • 57
  • 5
-1

Let's clean this code up:

#instead of an index counter, python provide `enumerate`
# so that you can have the counter as part of your loop
#index = -1
f_t = []
for index, f in enumerate(inputs[:,0]):
#   index = index +1
   def F_analytic(k, m, c):
      #these two lines are redundant. You're just returning an expression
      # so this whole function can be a lambda
      F_t = k*m*c*f 
      return F_t
   #why are you creating an inner list for each index position,
   # and then appending the function to it?
   #even if you wanted to have the inner list, you could do it in one step
   f_t.append([])
   f_t[index].append(F_analytic)

If we make the specified changes, we end up with:

f_t = [(lambda k, m, c: k*m*c*f) for f in inputs[:,0]]

Of course a much simpler approach would be simply to calculate the inputs to the product, including f, and multiply directly.

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • This won't work - `f` will have the value of last iteration _in all_ functions - see: https://stackoverflow.com/a/18915672/281545 – Mr_and_Mrs_D Jan 19 '20 at 13:48