Receiving function as another function´s parameter - python-3.x

Let´s say I have 2 functions like these ones:
def list(n):
l=[x for x in range(n)]
return l
def square(l):
l=list(map(lambda x:x**2,l))
print(l)
The first one makes a list from all numbers in a given range which is "n" and the second one receives a list as a parameter and returns the squared values of this list.
However when I write:
square(list(20))
it raises the error "map object cannot be interpreted as an integer" and whenever I erase one of the functions above and run the other one it runs perfectly and I have no idea what mistake I made.

You redefined the standard function list()! Rename it to my_list() and clean the code accordingly.
As a side note, your function list() is doing exactly what list(range(n)) would do. Why do you need it at all? In fact, for most purposes (including your example), range(n) alone is sufficient.
Finally, you do not pass a function as a parameter. You pass the value generated by another function. It is not the same.

Related

How to tackle the error str object is not callable

Whenever I am trying to run the given code it always gives the error 'str' object is not callable.
Somebody please tell me what is wrong with the code.
Here is the code:
def intel():
c=0
for i in num(1,9):
if((num[i]%2)==0):
c=c+1
return c
num = input()
out= intel()
print(out)```
Bachchu, welcome! There are a few different things going on here:
As usr2564301 explained, the TypeError: 'str' object is not callable is Traceback for statement for i in num(1,9): because the num() function does not exist unless you define one yourself. That is to say that functions like print() are built-in to Python such that you need not import additional modules to have automatic access to them. The num() function does not exist in the default 'namespace' which you have access to. Perhaps you did define one in another module and forgot to import it, or perhaps you did not mean to call that as a function, but it caused the error because unless you have visibility to it (for example through a def or import) then it does not exist as far as Python is concerned.
This segues into Carl Brubaker's assumption that you meant to use the range() function instead of num() altogether. The range() function would generate a list of [1,2,3,4,5,6,7,8] for your code to iterate through. It starts at the first argument (1) and goes up to but not including the second argument (9-1 = 8). I will add that perhaps, if you did indeed intend for the generation of a list, you probably meant to include 9 in the list, in which case you would need to use range(1,10).
As far as num() and input() are concerned, I don't think you are trying to define a num() function by entering it at the keyboard and assigning it to variable num via a call to the input() function.
The num = input() statement accepts user input from the keyboard and assigns it in string format to the variable num. As Carl Brubaker explained, you will need to convert (or cast if you are familiar with other languages) that data to int() before comparing it numerically. You can easily do this by wrapping the input() call:
num = int(input())
or like this:
num = input()
num = int(num)
One last piece of two-cents: The input() function can be passed a prompt string to present to the user so that when the control is passed to the terminal, the prompt will indicate to the user that it is expecting something. Here's an example:
num = int(input('Please enter a number: '))
As expected, this will present the user, at the terminal (command prompt), with the following:
Please enter a number:
Note that the blank space is a spacer so that the user's data will begin one space after the colon (for the sake of clarity).
At this juncture, we could guess what your objective is, but it would be best if you first cleaned up what we have pointed out here, then followup with outstanding issues, if any remain.

Why UnboundLocalError doesn't occur with lists?

I have a question regarding a tutorial problem.
Write a function make_monitored that takes as input a function, f, that itself takes one input. The result returned by make_monitored is a third function, say mf, that keeps track of the number of times it has been called by maintaining an internal counter. If the input to mf is the special string "how-many-calls?", then mf returns the value of the counter. If the input is the special string "reset-count", then mf resets the counter to zero. For any other input, mf returns the result of calling f on that input and increments the counter.
I have the following solution which works, surprisingly.
def make_monitored(f):
calls=[0]
def helper(n):
if n=="how-many-calls?":
return calls[0]
elif n=="reset-count":
calls[0]=0
else:
calls[0]+=1
return f(n)
return helper
I recalled reading about UnboundLocalError here: UnboundLocalError in Python
My question would be why won't calls[0]+=1 trigger that error? I made an assignation to a variable outside the local scope of the third function helper , and it seems a similar solution that uses instead calls.append(1) (the rest of the code correspondingly becomes len(calls) and calls.clear()) also bypasses that error.

Is this recursive?

Second attempt here, I just wanted to know if this is considered a recursive function.
The purpose of the function is to take a string and
if the the first element is equal to the last element
then append the last element to a list and return nothing,
else call istelf and pass the same string from index [1]
finally append the first element to the list
I know that error checking needs to be done on the if statement. However I am only doing this to try and get my head around recursion...Struggling to be honest.
Also I would never write a program like this if it where anything but trivial I just wanted to check if my understanding is correct so far.
def parse(theList):
theList.reverse()
parsedString = ''.join(theList)
return parsedString
def recursiveMessage(theString):
lastElement = theString[len(theString) - 1]
if theString[0] == lastElement:
buildString.append(theString[0])
return None
else:
recursiveMessage(theString[1::])
buildString.append(theString[0])
toPrint = "Hello Everyone!"
buildString = []
recursiveMessage(toPrint)
print(parse(buildString))
Thanks again.
Is this recursive?
If at any point in a function's execution it calls itself, then it is consider recursive. This happens in your example, so recursiveMessage is indeed recursive.
so which is quicker recursion or iteration?
Recursion is usually much slower and consumes more space due to a new stack frame having to be created on the call stack each recursive call. If you know your recursive function will need to be run many times, iteration is the best route.
As an interesting side note, many compilers actually optimize a recursive function by rolling it out into a loop anyways.

A Function That Counts The Number of Loops

Write a function multisplit that consumes two positive integers total and split and produces the number of times total is repeatedly divided into split even pieces before each piece is of size at most 1. For example, the value returned by multisplit(8, 2) will be 3, since 8 can be split into 2 pieces of size 4, which are then each split into 2 pieces of size 2, which are then each split into 2 pieces of size 1 (at which point no further splitting takes place since the pieces are of size at most 1).
total= int(input("Total:"))
split= int(input("Split:"))
def multisplit(total,split):
x=o
while value>=1:
value= total//split
x= x+1
return x
print(x)
It's telling me that the name 'x' is not defined
There are several issues with the code you posted:
In python, the contents of a function must be indented.
def myfunction():
# code inside the function goes here
# code after you've unindented is not in the function
You didn't define your value variable before using it.
Assuming that your final line gets appropriately unindented, so that it won't be completely ignored because of being inside the function, but after the return statement:
You're trying to print the value of a variable that was defined in a different scope. Specifically, you defined x inside the function, and now you're trying to look at it outside the function.
You never called your function...
If I understand what you're trying to do, you want to call the function inside print. i.e.: print(multisplit(total, split))

How to create an array of functions which partly depend on outside parameters? (Python)

I am interested in creating a list / array of functions "G" consisting of many small functions "g". This essentially should correspond to a series of functions 'evolving' in time.
Each "g" takes-in two variables and returns the product of these variables with an outside global variable indexed at the same time-step.
Assume obs_mat (T x 1) is a pre-defined global array, and t corresponds to the time-steps
G = []
for t in range(T):
# tried declaring obs here too.
def g(current_state, observation_noise):
obs = obs_mat[t]
return current_state * observation_noise * obs
G.append(g)
Unfortunately when I test the resultant functions, they do not seem to pick up on the difference in the obs time-varying constant i.e. (Got G[0](100,100) same as G[5](100,100)). I tried playing around with the scope of obs but without much luck. Would anyone be able to help guide me in the right direction?
This is a common "gotcha" to referencing variables from an outer scope when in an inner function. The outer variable is looked up when the inner function is run, not when the inner function is defined (so all versions of the function see the variable's last value). For each function to see a different value, you either need to make sure they're looking in separate namespaces, or you need to bind the value to a default parameter of the inner function.
Here's an approach that uses an extra namespace:
def make_func(x):
def func(a, b):
return a*b*x
return func
list_of_funcs = [make_func(i) for i in range(10)]
Each inner function func has access to the x parameter in the enclosing make_func function. Since they're all created by separate calls to make_func, they each see separate namespaces with different x values.
Here's the other approach that uses a default argument (with functions created by a lambda expression):
list_of_funcs = [lambda a, b, x=i: a*b*x for i in range(10)]
In this version, the i variable from the list comprehension is bound to the default value of the x parameter in the lambda expression. This binding means that the functions wont care about the value of i changing later on. The downside to this solution is that any code that accidentally calls one of the functions with three arguments instead of two may work without an exception (perhaps with odd results).
The problem you are running into is one of scoping. Function bodies aren't evaluated until the fuction is actually called, so the functions you have there will use whatever is the current value of the variable within their scope at time of evaluation (which means they'll have the same t if you call them all after the for-loop has ended)
In order to see the value that you would like, you'd need to immediately call the function and save the result.
I'm not really sure why you're using an array of functions. Perhaps what you're trying to do is map a partial function across the time series, something like the following?
from functools import partial
def g(current_state, observation_noise, t):
obs = obs_mat[t]
return current_state * observation_noise * obs
g_maker = partial(g, current, observation)
results = list(map(g_maker, range(T)))
What's happening here is that partial creates a partially-applied function, which is merely waiting for its final value to be evaluated. That final value is dynamic (but the first two are fixed in this example), so mapping that partially-applied function over a range of values gets you answers for each value.
Honestly, this is a guess because it's hard to see what else you are trying to do with this data and it's hard to see what you're trying to achieve with the array of functions (and there are certainly other ways to do this).
The issue (assuming that your G.append call is mis-indented) is simply that the name t is mutated when you loop over the iterator returned by range(T). Since every function g you create stores returns the same name t, they wind up all returning the same value, T - 1. The fix is to de-reference the name (the simplest way to do this is by sending t into your function as a default value for an argument in g's argument list):
G = []
for t in range(T):
def g(current_state, observation_noise, t_kw=t):
obs = obs_mat[t_kw]
return current_state * observation_noise * obs
G.append(g)
This works because it creates another name that points at the value that t references during that iteration of the loop (you could still use t rather than t_kw and it would still just work because tg is bound to the value that tf is bound to - the value never changes, but tf is bound to another value on the next iteration, while tg still points at the "original" value.

Resources