Is there any operator.unpack in Python? - python

Is there any built-in version for this
def unpack(f, a):
return f(**a) #or ``return f(*a)''
Why isn't unpack considered to be an operator and located in operator.*?
I'm trying to do something similar to this (but of course want a general solution to the same type of problem):
from functools import partial, reduce
from operator import add
data = [{'tag':'p','inner':'Word'},{'tag':'img','inner':'lower'}]
renderer = partial(unpack, "<{tag}>{inner}</{tag}>".format)
print(reduce(add, map(renderer, data)))
as without using lambdas or comprehensions.

That is not the way to go about this. How about
print(''.join('<{tag}>{inner}</{tag}>'.format(**d) for d in data))
Same behavior in a much more Pythonic style.
Edit: Since you seem opposed to using any of the nice features of Python, how about this:
def tag_format(x):
return '<{tag}>{inner}</{tag}>'.format(tag=x['tag'], inner=x['inner'])
results = []
for d in data:
results.append(tag_format(d))
print(''.join(results))

I don't know of an operator that does what you want, but you don't really need it to avoid lambdas or comprehensions:
from functools import reduce
from operator import add
data = [{'tag':'p','inner':'Word'},{'tag':'img','inner':'lower'}]
print(reduce(add, map("<{0[tag]}>{0[inner]}</{0[tag]}>".format, data)))
Seems like it would be possible to generalize something like this if you wanted.

Related

Multiprocessing : Use process_map with many arg function

I found this answer (https://stackoverflow.com/a/59905309/7462275) to display a progress bar very very simple to use. I would like to use this simple solution for functions that take many arguments.
Following, the above mentioned answer, I write this code that works :
from tqdm.contrib.concurrent import process_map
import time
def _foo(my_tuple):
my_number1, my_number2 = my_tuple
square = my_number1 * my_number2
time.sleep(1)
return square
r = process_map(_foo, [(i,j) for i,j in zip(range(0,30),range(100,130))],max_workers=mp.cpu_count())
But I wonder, if it is the correct solution (using a tuple to assign function variable) to do that. Thanks for answer

Map list of functions to list of arguments in python

I have a simple example as so:
import numpy as np
func_dict1 = {0: np.sin, 1: np.cos, 2: np.tan}
out = map(func_dict1.get, np.array([0, 2, 0]))
Here I am picking out three functions by their dictionary keys. Now I want to pass unique arguments to each function like so:
[f(x) for f,x in zip(out, [3,1,2])]
which renders the output:
[0.1411200080598672, 1.557407724654902, 0.9092974268256817]
But how can I do this with map?
I thought this would work, but it does not:
map(out, [3,1,2])
Where am I going wrong? And is there any benefit to using map over list comprehension? My prior is that it is faster but I confess to not being an expert on the subject.
map is designed to take a single function and apply it to every item in an iterable. You are applying a different function to different items. I think the list comprehension is an elegant way of doing it.
WARNING: you probably don't want to use map and this answer might confuse you more than it helps ;).
However, as you asked how you can make map do this and as it's python, let's take the challenge: one way to achieve what you want is by wrapping your out in an object that is callable (so behaves like a function) and on each call also advances to the next function. For example like this:
# yours
import numpy as np
func_dict1 = {0: np.sin, 1: np.cos, 2: np.tan}
out = map(func_dict1.get, np.array([0, 2, 0]))
# extend like this
class FuncIterCaller:
def __init__(self, funcs):
self.funcs = funcs
def __call__(self, *args, **kwds):
return next(self.funcs)(*args, **kwds)
res = map(FuncIterCaller(out), [3,1,2])
# to see what's inside:
print(list(res))

Pythonic way to re-apply a function to its own output n times?

Assume there are some useful transformation functions, for example random_spelling_error, that we would like to apply n times.
My temporary solution looks like this:
def reapply(n, fn, arg):
for i in range(n):
arg = fn(arg)
return arg
reapply(3, random_spelling_error, "This is not a test!")
Is there a built-in or otherwise better way to do this?
It need not handle variable lengths args or keyword args, but it could. The function will be called at scale, but the values of n will be low and the size of the argument and return value will be small.
We could call this reduce but that name was of course taken for a function that can do this and too much more, and was removed in Python 3. Here is Guido's argument:
So in my mind, the applicability of reduce() is pretty much limited to
associative operators, and in all other cases it's better to write out
the accumulation loop explicitly.
reduce is still available in python 3 using the functools module. I don't really know that it's any more pythonic, but here's how you could achieve it in one line:
from functools import reduce
def reapply(n, fn, arg):
return reduce(lambda x, _: fn(x), range(n), arg)
Get rid of the custom function completely, you're trying to compress two readable lines into one confusing function call. Which one do you think is easier to read and understand, your way:
foo = reapply(3, random_spelling_error, foo)
Or a simple for loop that's one more line:
for _ in range(3):
foo = random_spelling_error(foo)
Update: According to your comment
Let's assume that there are many transformation functions I may want to apply.
Why not try something like this:
modifiers = (random_spelling_error, another_function, apply_this_too)
for modifier in modifiers:
for _ in range(3):
foo = modifier(foo)
Or if you need different amount of repeats for different functions, try creating a list of tuples:
modifiers = [
(random_spelling_error, 5),
(another_function, 3),
...
]
for modifier, count in modifiers:
for _ in range(count):
foo = modifier(foo)
some like recursion, not always obviously 'better'
def reapply(n, fn, arg):
if n:
arg = reapply(n-1, fn, fn(arg))
return arg
reapply(1, lambda x: x**2, 2)
Out[161]: 4
reapply(2, lambda x: x**2, 2)
Out[162]: 16

Partially unpack parameters in python

I know in Python we can unpack parameters from a tuple or list:
def add(x,y,z):
return x + y + z
xyz = (1,2,3)
s = add(*xyz)
But what is the proper way to accomplish something like this:
xy = (1,2)
s = add(*xy, 3)
SyntaxError: only named arguments may follow *expression
I can do this:
s = add(*xy + (3,))
but that looks ugly and badly readable, and if I have a few more variables in there it would be very messy.
So, is there a cleaner way to deal with such situation?
If you name your arguments; you can then proceed as you like:
>>> def foo(x=None,y=None,z=None):
... return x+y+z
...
>>> s = foo(*(1,2),z=3)
>>> s
6
Now if you do it like this, you can't override keyword arguments, so foo(*(1,2), y=3) will not work; but you can switch the order around as you like foo(z=3, *(1,2)).
I don't know that this is much cleaner, but since we're talking about partials..
from functools import partial
sum_ = partial(add,*xy)(3)
The pep for this has been proposed long back in 2007. You can take a look at it here - http://www.python.org/dev/peps/pep-3132
Although it might not come in py3.4 but it is certainly accepted by Guido & is proposed to come in some python 3 release.
sum = add(3, *xy)
Hope this will do.
The prototype for a method declaration in python is:
def method1(arg1,arg2, *args, **kwargs):
....your code.....

FOOn(i, j, k) notation for nd numpy array in weave.inline()'s support_code argument? Are there any alternatives?

I want to use support_code to define functions that interact with nd numpy arrays. Inside the code argument, the FOO3(i, j, k) notation works, but only in it, not in support_code.Something like this:
import scipy
import scipy.weave
code = '''return_val = f(1);'''
support_code = '''int f(int i) {
return FOO3(i, i, i);
}''''
foo = scipy.arange(3**3).reshape(3,3,3)
print(scipy.weave.inline(code, ['foo'], support_code=support_code))
The concept of support code is mainly to do some includes. In your case, I guess the function should look something like this:
import scipy
import scipy.weave
def foofunc(i):
foo = scipy.arange(3**3).reshape(3,3,3)
code = '''#do something lengthy with foo and maybe i'''
scipy.weave.inline(code, ['foo', 'i']))
return foo[i,i,i]
You don't need support code at all, for what you're trying to do. You also don't have any speed improvement, when you try to do a function return in C instead of doing that in python, also array access is neglectable compared to the cost of the function call. To get a better idea, when and how weave can help you, to speed up your code, have a look here.

Categories