I have the need to take a function of n parameters and n lists of values and apply the function to each possible permutation of arguments. I have looked in itertools and none of the functions are quite right. The following is my attempt. Can someone explain what I am doing wrong? Thanks.
def CrossReference(f, *args):
result = []
def inner(g, *argsinner):
rest = argsinner[1:]
a = argsinner[0]
if type(a) is not list:
a = [a]
for x in a:
h = partial(g, x)
if len(rest) > 0:
inner(h, rest)
else:
result.append(h())
inner(f, args)
return result
Here is my example test and error:
def sums(x,y,z):
return x+y+z
CrossReference(sums, [1,2,3], 4, [5,6,7])
Traceback (most recent call last): File "", line 1,
in File "", line 13,
in CrossReference File "", line 12, in inner
TypeError: sums() takes exactly 3 arguments (1 given)
The problem is in the way you call your inner function. You define your function header as:
def inner(g, *argsinner):
But you call your function like:
inner(f, args)
And:
inner(h, rest)
This means that you will end up with a single tuple (monotuple?) containing the tuple of your args. You can either change your function definition to:
def inner(g, argsinner):
Or change your calling to:
inner(h, *rest)
def sums(x,y=0,z=0):
return x+y+z
def apply(fn,*args):
for a in args:
try:
yield fn(*a)
except TypeError:
try:
yield fn(**a)
except TypeError:
yield fn(a)
print list(apply(sums,[1,2,3], 4, [5,6,7]))
is one way you might do it (not the only way though)
Related
I have looked around on SO and surprisingly not found an answer to this question. I assume this is because normally inner/nested functions are used for something in particular (eg. maintaining an environment variable, factories) as opposed to something trivial like I'm trying to use them for. In any case, I can't seem to find any information on how to properly call an inner function from an outer function without having to declare inner() above outer() in the file. The problem is from this problem on HackerRank (https://www.hackerrank.com/challenges/circular-array-rotation/problem).
def circularArrayRotation(a, k, queries):
def rotateArrayRightCircular(arr: list, iterations: int) -> list:
"""
Perform a 'right circular rotation' on an array for number of iterations.
Note: function actually moves last 'iterations' elements of array to front of array.
>>>rotateArrayRightCircular([0,1,2], 1)
[2,0,1]
>>>rotateArrayRightCircular([0,1,2,3,4,5], 3)
[3,4,5,0,1,2]
>>>rotateArrayRightCircular([0,1,2,3,4,5], 6)
[0,1,2,3,4,5]
"""
return arr[-1 * iterations:] + arr[0:-1 * iterations]
k = k % len(a)
a = rotateArrayRightCircular(a, k)
res = []
for n in queries:
res.append(a[n])
return res
The code above does what I want it to, but it's somehow inelegant to me that I have to put the inner function call after the inner function definition. Various errors with different attempts:
# trying 'self.inner()'
Traceback (most recent call last):
File "solution.py", line 52, in <module>
result = circularArrayRotation(a, k, queries)
File "solution.py", line 13, in circularArrayRotation
a = self.rotateArrayRightCircular(a, k)
NameError: name 'self' is not defined
# Removing 'self' and leaving the definition of inner() after the call to inner()
Traceback (most recent call last):
File "solution.py", line 52, in <module>
result = circularArrayRotation(a, k, queries)
File "solution.py", line 13, in circularArrayRotation
a = rotateArrayRightCircular(a, k)
UnboundLocalError: local variable 'rotateArrayRightCircular' referenced before assignment
Any idea how I could include def inner() after the call to inner() without throwing an error?
As a function is executed from top to bottom, and a function is put into existence as the function is processed, what you want is just not possible.
You could put the function before the outer one, making it outer itself, possibly adding some parameters (not necessary here). (BTW, it looks so generic that other parts of the code might want to use it as well, so why not outer?)
But otherwise, you are stuck. It is essetially the same situation as in
def f():
print(a) # a doesn't exist yet, so this is an error
a = 4
Well, you could do it this way:
def circularArrayRotation(a, k, queries):
def inner_code():
k = k % len(a)
a = rotateArrayRightCircular(a, k)
# BTW, instead of the following, you could just do
# return [a[n] for n in queries]
res = []
for n in queries:
res.append(a[n])
return res
def rotateArrayRightCircular(arr: list, iterations: int) -> list:
"""
Perform a 'right circular rotation' on an array for number of iterations.
Note: function actually moves last 'iterations' elements of array to front of array.
>>>rotateArrayRightCircular([0,1,2], 1)
[2,0,1]
>>>rotateArrayRightCircular([0,1,2,3,4,5], 3)
[3,4,5,0,1,2]
>>>rotateArrayRightCircular([0,1,2,3,4,5], 6)
[0,1,2,3,4,5]
"""
return arr[-1 * iterations:] + arr[0:-1 * iterations]
return inner_code()
but I don't see that you gain anything from it.
This is not possible in Python, but is possible in other languages like Javascript and PHP. It is called function hoisting.
First of all, I'm super new to python and I actually search for my problem but the examples were to heavy to understand.
Here is my homework; I need a function which takes two functions as an argument and returns if the results of the two functions are same or not? Basically, it will give either TRUE of FALSE.
For that I wrote:
def f(x,y,z):
k=x(*z)
l=y(*z)
return k == l
The previos code I wrote for single function was working but when I modified it for two function as above, it gives an error as following :
import math
>>> f(math.sqrt,math.cos,5)
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
f(math.sqrt,math.cos,5)
File "D:/Users/karabulut-ug/Desktop/yalanmakinesi.py", line 2, in f
k=x(*z)
TypeError: sqrt() argument after * must be a sequence
>>>
I could not figured it out since the error giving function is normally does not take a sequence. So I dont think it makes a sense :) Any help is appreciated.. Thanks :)
z is just a single number, but the * argument expansion syntax requires that you pass in a sequence (like a list, tuple or str, for example).
Either remove the * (and make your function work for just single arguments), or use *z in the function signature to make z a tuple of 0 or more captured arguments:
def f(x, y, z):
k = x(z)
l = y(z)
return k == l
or
def f(x, y, *z):
k = x(*z)
l = y(*z)
return k == l
The latter now works for functions with more than one argument too:
f(math.pow, math.log, 10, 10)
If you added a **kw argument to the signature, then keyword arguments could be handled too:
def f(x, y, *args, **kwargs):
k = x(*args, **kwargs)
l = y(*args, **kwargs)
return k == l
Here I renamed z to args to better reflect its purpose.
The syntax *z invokes argument unpacking on z. When z is just an integer, there is no iterator behavior defined, and so you see this error. Try:
>>> f(math.sqrt, math.cos, [5])
You need to remove the *. Its for unpacking. So:
def f(x,y,z):
k=x(z)
l=y(z)
return k == l
You use the * operator when you want to pass in an iterable object, like a list or tuple as something thats split up. So, for example:
a = [1,2,3,4,5]
So, for an arbitrary function, f:
f(*a) = f(1,2,3,4,5)
I was implementing the dynamic programming algorithm and I got this error. This is my code:
def shoot(aliens):
s=[0]*10
s[0]=0
s[1]=0
for j in xrange(2,len(aliens)):
for i in xrange(0,j):
s[j]=max(s[i] + min(aliens[j],fib(j-i))) <---Error here
print s[len(aliens)-1]
return s[len(aliens)-1]
def fib(n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n-1) + fib(n-2)
aliens=[1,10,10,1]
print shoot(aliens)
it says that:
Traceback (most recent call last):
File "module1.py", line 30, in <module>
print shoot(aliens)
File "module1.py", line 19, in shoot
s[j]=max(s[i] + min(aliens[j],fib(j-i)))
TypeError: 'int' object is not iterable
Please help me
UPDATE:
oh, I get it.
I mean
s[j]=max(s[i] + min(aliens[j],fib(j-i)))
But im wrong.
so, I edited it like that, but I do not know how to use max() to take out the largest in an array.
b=0
for j in xrange(2,len(aliens)):
for i in xrange(0,j):
a[b]=(s[i] + min(aliens[j],fib(j-i)))
b+=1
s[j]=Largest(a[b]); <--How can I do that with Max() function
max and min functions require several arguments or a range of elements. Your call to min() has two arguments (ok), but your call to max() has only one. Not sure what you want to maximize here...
You are doing something like following:
>>> max(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
Did you want to do this?
s[j] = max(s[i], min(aliens[j],fib(j-i)))
or
s[j] = max(s[j], s[i] + min(aliens[j],fib(j-i)))
max needs an iterable argument.
max(...)
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
But what you passed to it by s[i] + min(aliens[j],fib(j-i)) is an int. What you want may be s[j]=max(s[i], min(aliens[j],fib(j-i)))
It means you cannot iterate over a single int object.
max() and min() want either a number of values of whose they return the largest resp. the smallest, or they want an objkect which can be iterated over.
Your max() call is executed with one single argument which, then, should be iterable, but isn't.
It should be, s[j] = max(s[i], min(aliens[j], fib(j-i))), isn't it?
http://docs.python.org/2/library/functions.html#max
max(iterable[, key])
max(arg1, arg2, *args[, key])
didn't you mean:
s[j] = max(s[i], min(aliens[j],fib(j-i)))
I'm trying to build a python class that parses a string and if it matches a regex that looks
like a function call attempt to call that function on the class, passing in any parameters.
For example a string like "foo("a", 20")" would translate to something like self.foo("a", 20).
Here is the code that I have so far..
class FooTranslate(object):
def create_string(self, letter, size):
return letter*size
def run_function(self, func_str):
match = re.match("([\w_]+)\((|[\W\d\w\,]+)\)", func_str)
if match == None:
print "Couldn't match a regex!"
return False
else:
func, fargs = match.groups()
try:
if fargs == "":
return self.__getattribute__(func)()
else:
return self.__getattribute__(func)(eval(fargs))
except AttributeError, e:
print "Invalid function call: %s" % (func)
return False
This code works in the basic cases...
In [1018]: foot = FooTranslate()
In [1019]: foot.run_function("foo()")
Foo!
In [1020]: foot.run_function("bar(2)")
FooFoo
However in the case of using 2 argument functions:
In [1021]: foot.run_function("create_string('a', 2)")
in run_function(self, func_str)
24 return self.__getattribute__(func)()
25 else:
---> 26 return self.__getattribute__(func)(eval(fargs))
27 except AttributeError, e:
28 print "Invalid function call: %s" % (func)
TypeError: create_string() takes exactly 3 arguments (2 given)
The reason why is that the eval() call returns fargs as a tuple, which create_string()
takes as only a single argument. Any idea how I can pass a variable number of arguments
through to a function call? Or have a better alternative way to do this?
You can use the * operator to explode a tuple into separate arguments to a function. For example:
def f(a, b, c):
print a, b, c
If I call f(...) like this:
f((1,2,3))
I get an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 3 arguments (1 given)
But if I call it like this:
f(*(1,2,3))
I get:
1 2 3
The * operator will even work if the function takes a variable number of arguments. For example, given the following function:
def f2(a, b, *args):
print a, b,
for x in args:
print x,
print
If I call f2(*(1,2,3,4,5)) it prints:
1 2 3 4 5
from celery.task import Task
class Decayer(Task):
def calc_decay_value(self, x):
y = (1.0/(2^x))
return y
def calc_decay_time(self, x):
y = 2^x
return y
def run(self, d, **kwargs):
#do stuff.
return 0
>>> decayer = tasks.Decayer(r)
Traceback (most recent call last):
File "scanDecay.py", line 31, in <module>
decayer = tasks.Decayer(r)
TypeError: object.__new__() takes no parameters
Two errors
1) Your class doesn't have an __init__ function. Either add one, or use this instead:
decayer = tasks.Decayer()
2) You are trying to raise an integer to the power of a float, but ^ means xor and cannot be used on floats. Use ** instead of ^:
y = 2 ** x
The problem seems due to decayer = tasks.Decayer(r) call and tasks.Decayer is not designed to take a argument, because Task does not define a __init__ method which can take one.