I am trying to do multiplication recursion (multiplying all the values of a container) in Python. The function receives the elements of the list as positional argument(*n). On execution I receive the error saying "Maximum recursion depth reached". However, the code works fine if I simply use n instead of *n and send the elements in a list.
Code not working:
def multiply(*n):
if n:
return n[0]*multiply(n[1:])
else:
return 1
multiply(5,1,4,9)
Working code:
def multiply(n):
if n:
return n[0]*multiply(n[1:])
else:
return 1
multiply([5,1,4,9])
In the first piece of code, the expression
multiply(n[1:])
is calling multiply with only one argument. Namely, the rest of the list. In order to call it with arguments equal to the contents of the list n[1:], you use the splat operator again, like so:
multiply(*n[1:])
When you tell a function to expect an arbitrary number of positional arguments with *n, you need to accommodate it in that format: with multiple arguments, not with a single iterable that contains all the arguments. If you have a single iterable whose elements should be used as arguments, you have to unpack it with * when you call it. The second function works because it's expecting a single, iterable argument, and you send it a single, iterable argument.
Replace n[1:] with *n[1:].
Related
I wanted to know how to work with an array as a functional argument in Python. I will show a short example:
def polynom(x, coeff_arr):
return coeff_arr[0]+ coeff_arr[1]+x +coeff_arr[2]*x**2
I obviously get the error that 2 positional arguments are needed but 4 were given when I try to run it, can anybody tell me how to do this accept just using (coeff_arr[i]) in the argument of the function?
Cheers
Your question is missing the code you use to call the function, but from the error I infer that you are calling it as polynom(x, coefficient1, coefficient2, coefficient3). Instead you need to either pass the coefficients as a list:
polynom(x, [coefficient1, coefficient2, coefficient3])
Or use the unpacking operator * to define the function as follows, which will take all positional arguments after x and put them into coeff_arr as a list:
def polynom(x, *coeff_arr):
(The unpacking operator can also be used in a function call, which will do the opposite of taking a list and passing its elements as positional arguments:
polynom(x, *[coefficient1, coefficient2, coefficient3])
is equivalent to
polynom(x, coefficient1, coefficient2, coefficient3)
)
I am looking for a high order function in python that takes in a function as parameter and a list of corresponding parameters, and call the function on the parameter list. Something like:
def exec(func,paramlist):
return CALL(func,paramlist)
The paramlist length is undetermined, since it goes with each func passed in. The CALL should be able to extract the elements in the list and put each parameter in the right slot and make the function call.
For reference, in Q language there is this "apply" function that handles generic function calls:
f1: {x}
f2: {x+y}
execFunction: {[fun;param] .[fun;param] }
execFunction[f1;enlist 1] // result is 1
execFunction[f2;(1 2)] // result is 3
If func expects multiple parameters and paramlist is a list of parameters, is as simple as this:
func(*paramlist)
Python used to have an apply function but it was removed in Python 3 because it is so easy to unpack a list into individual arguments using the * operator. In fact an apply function can be written like so:
def apply(func, paramlist)
return func(*paramlist)
This is so trivial, of course, that you wouldn't bother to write a function for it; you'd just write func(*paramlist) wherever you needed it.
I'm trying to write a function which gets as parameters a list of functions, and parameters for the first one. It then calls them in order, passing the output of the previous one into the next one. (Obviously for this to work all functions must expect the same number of parameters and return the same number of values).
Here's what I tried:
def chain(functions, *first_func_params):
params = first_func_params
for func in functions:
params = func(*params)
However this works only if all the functions return tuples ('multiple values') or other sequence types, because only sequence types can be unpacked into the parameter list of a function.
If the functions simply return single values, chain doesn't work.
I could simply check if func's output is a tuple or not and act accordingly. But is there a more elegant solution?
How would you implement this?
You could use:
if not isinstance(params, tuple):
params = (params,)
Or catch the TypeError exception that will be raised if you try to use * before an unpackable object.
If I have a function in Python like this:
def multiply(a, b)
return a * b
How can I call PyObject_CallObject when it will give me an error if I have more than two arguments? There may be a much better way of calling a function from C++ but I am very new to the Python/C API
From the documentation:
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args)
Return value: New reference.
Call a callable Python object callable_object, with arguments given
by the tuple args. If no arguments are needed, then args may be NULL.
Returns the result of the call on success, or NULL on failure. This is
the equivalent of the Python expression callable_object(*args).
In other words:
You can pass more than one argument to the function by passing a single tuple containing the arguments. So you'd have to build a tuple containing x and y (i.e. (x, y)) and then pass the tuple as single parameter to PyObject_CallObject(multiply, the_tuple) this will be equivalent to multiply(x, y).
It does not represent the most general call. The most generic call is PyObject_Call which takes two arguments: a tuple of positional arguments and a dictionary of keyword arguments.
There are also the PyObject_CallFunction* functions that are similar to PyObject_CallObject but they avoid having to create the tuple and allow multiple parameters.
executor.map() TypeError: zip argument #2 must support iteration
when I run it ,just generated TypeError: zip argument #2 must support iteration.
can anyone help me fix this problem ?
import time, concurrent.futures
lst100=[i for i in range(100)]
t1=time.clock()
print(list(map(str,lst100)))
t2=time.clock()
print(t2-t1)
t3=time.clock()
with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
future_to_url = executor.map(str,lst100, 60)
print(list(future_to_url))
t4=time.clock()
print(t4-t3)
concurrent.futures.Executor.map is semantically identical to the built-in function map. The second and subsequent non-keyword arguments specify the iterables to apply the given function to.
In your case, you're saying "Here are two iterables: a list of 100 elements (lst100) and the integer 60. Please call the function str() on each pair of elements a and b coming form the two iterables respectively, and return the list of results." But since the integer 60 is not actually an iterable object, it fails.
Assuming you wanted to specify a timeout of 60 seconds, you need to pass it as a keyword argument like so:
future_to_url = executor.map(str, lst100, timeout=60)
Keyword arguments are distinguished from positional arguments by the presence of the name= prefix before the value being passed. In this case, the argument name is timeout.