Using "*" inside python - python

I am supposed to use find out how to use "*" to sum up several values.
For example:
sum_all(1, 2, 3, 4, 5)
15
sum_all(49, 51)
100
Given a general function like :
def sum_all(*args)
I am unsure how to implement the * within the code.

def sum_all(*args):
total = 0
for arg in args:
total += sum(arg)
return total
To be different from the others which i think posted at the same time as me, i'll explain and come up with another solution.
When doing *args you can look at it this way:
def sum_all([arg1, arg2, arg3, ...]):
Which would tedious to code and since you don't know how many parameters are given, you do *args instead, which dynamically takes a "endless" amount of arguments in a list format.
The most neat way i can think of:
def sum_all(*args):
return sum(sum(arg) for arg in args)
This assumes the input is something along the lines of:
sum_all([1,2,3], [5,5], [10,10])
If not just skip one of the sums:
def sum_all(*args):
return sum(args)

You can treat the passed in variable as an iterable.
sum_nums = 0
for val in args:
sum_nums += val
A good read would be the top answer in this question.

def sum_all(*args):
s = 0
for n in args:
s = s + n
return s

In short:
def sum_all(*args):
return sum(args)
*args represent here a sequence of positional arguments, that you can later iterate over. Fortunately, builtin sum() takes single iterable as argument, so you can just pass it there.
More info you can find in docs:
http://docs.python.org/2/faq/programming.html#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another

Just 2 lines of code :)
def sum_all(*args):
return (sum(args[0])

You can try as,
def sum_all(*args):
return sum([i for i in args])

Related

How to package a sequence functions that act on parameter in order in Python

Imagine there are three functions, all them accept and return the same type args.
Normally, we can write it as fun3(fun2(fun1(args)), this can be say that a sequence function act on parameter in order, which likes one variety Higher-order functions "map".
You know in Mathematica, we can write this as fun3#fun2#fun1#args.
Now the question is that can we integrate fun3#fun2#fun1 as another fun without modifying their definition, so fun(args) can replace fun3(fun2(fun1(args)), this looks more elegant and concise.
def merge_steps(*fun_list):
def fun(arg):
result = arg
for f in fun_list:
result = f(result)
return result
return fun
def plus_one(arg):
return arg + 1
def double_it(arg):
return arg ** 2
def power_ten(arg):
return arg ** 10
combine1 = merge_steps(power_ten, plus_one, double_it)
combine2 = merge_steps(plus_one, power_ten, double_it)
combine1(3)
> 3486902500
or use lambda:
steps = [power_ten, plus_one, double_it]
reduce(lambda a, f: f(a), steps, 3)
> 3486902500
I think you can use Function Recursion in python to do this.
def function(args, times):
print(f"{times} Times - {args}")
if times > 0 :
function(args,times - 1)
function("test", 2)
Note: I just add times argument to not generate infinite loop.
I'm not certain I understand your question, but are you talking about function composition along these lines?
# Some single-argument functions to experiment with.
def double(x):
return 2 * x
def reciprocal(x):
return 1 / x
# Returns a new function that will execute multiple single-argument functions in order.
def compose(*funcs):
def g(x):
for f in funcs:
x = f(x)
return x
return g
# Demo.
double_recip_abs = compose(double, reciprocal, abs)
print(double_recip_abs(-2)) # 0.25
print(double_recip_abs(.1)) # 5.0

Is it possible to unpack values into several functions?

Is it possible to unpack elements in python and pass them directly into several functions without assigning them into a variable first?
e. g.
def my_function():
return (1, 2)
# Not sure how the syntax would look like?
(function_1(#first element here), function_2(#second element here)) <= my_function()
It is possible, to not assign your output to any variable, for example by calling the function twice, which theoretically would make only sense if the function is a pure function. However I do not find any useful example. I am curious why you would like to do it.
There is a way around achieving that goal.
This, it would require you to create your own method that does that.
Here is a simple approach of how you might want to do that.
In my example, there is a function called dissolve_args_to_fns which accepts functions and a list that hold values to the functions input.
dissolve_args_to_fns implementation
from typing import Tuple, Any
from collections.abc import Iterable
def dissolve_args_to_fns(*fns, inputs: Tuple[Any, ...]):
# If there are more inputs than there are functions, and vice-versa, throw error
if len(fns) != len(inputs):
raise ValueError('The numbers of functions dont match the number of inputs each function')
# Holds the output corresponding to each function
outputs = []
for i, fn in enumerate(fns):
# Individual input for each function
inp = inputs[i]
# Checks if the input for the function is an iterable
# If so, then its probably for an argument that need multiple arguments
if isinstance(inp, Iterable) :
fn_out = fn(*inp)
else:
fn_out = fn(inp)
outputs.append(fn_out)
# returns an output if, there is any function that has an output
# This extra checking step is not necessary
if any(map(lambda x: x is not None, outputs)):
return outputs
Now that the function is done, we can begin testing it out.
Below, are 3 custom functions, some of which have an output, and others which don't
def show(value):
print("Here is", value)
def blink(value, blink_count:int = 2):
print(f" *blink* {value}" * blink_count)
def full_name(first_name, last_name) -> str:
return "%s %s" % (first_name, last_name)
I'll also be using the sum in-built function to show how wide this implementation can be used
_, name, _, _sum = dissolve_args_to_fn(show, full_name, blink, sum, inputs=(1, 2, ("Mike", "Tyson"), ([10, 5],)))
print("My name is", name)
print("Sum is:", _sum)
Well that's it. This simple function now works like magic.
Happy coding.
PS: As you can see, the simple implementation doesn't work for keyword arguments, but feel free to hack the code as a you please
The following is to the effect of what you described in your further comments:
list1 = []
list2 = []
def my_function():
return (1, 2)
def function_1(x1):
list1.append(x1)
def function_2(x2):
list2.append(x2)
lam = lambda x: (function_1(x[0]), function_2(x[1]))
lam(my_function())
Verification:
>>> print(list1)
[1]
>>> print(list2)
[2]

*args in function with Python

I was trying to define a simple sum function in python.
My code is:
def sum_all_num(*args):
return sum(*args)
But I got error. I understand the *args will gather all arguments in a tuple, but why I can not use sum function to sum it?
sum() takes an iterable. Just remove the * and pass the args tuple directly.
Example:
x = 1, 2, 3
print(sum(x))
Results:
6
sum() takes only one argument (an iterable).
So, instead of unpacking args with *, just pass the args variable to it:
def sum_all_num(*args):
return sum(args)
Test:
>>> sum_all_num(1,2,3)
6

Is it possible to pass the same optional arguments to multiple functions?

I want to ask if there is a way to prevent unnecessary duplicate of code when passing the same arguments into a function's optional arguments.
Hopefully the following example provides a good idea of what I am trying to do:
def f(arg1):
def g(optional_1=0, optional_2=0, optional_3=0):
return arg1+optional_1+optional_2+optional_3
return g
b, c = 2, 3
f1 = f(1)
f2 = f(2)
calc_f1 = f1(optional_2=b, optional_3=c)
calc_f2 = f2(optional_2=b, optional_3=c)
As you can see, f1 and f2 only differ in the arg1 passed into f and afterwards I call them with the same variables for the same optional arguments.
It is fine when the code is short, but when I have over 10 optional arguments, it becomes unnecessarily long and redundant.
Is it possible to do something like
optional_variable_pair = #some way to combine them
calc_f1 = f1(optional_variable_pair)
calc_f2 = f2(optional_variable_pair)
so I get a more succinct and easy to read code?
Any function with multiple optional arguments is a bit smelly because:
you get so many argument combinations that it requires a large amount of testing.
because of all the options the function has to have alot of conditionals and routes which increase its cyclomatic complexity.
You can apply a refactoring to extract the whole argument list into an Object and have the function work on that object. This works really well if you can find a unifying name that describes your argument list and fits whatever metaphor you are using around the function. You can even invert the call so that the function becomes a method of the Object, so you get some encapsulation.
To answer the question you asked, the answer is yes. You can do almost exactly what you want using keyword argument unpacking.
def f(arg1):
def g(optional_1=0, optional_2=0, optional_3=0):
return arg1+optional_1+optional_2+optional_3
return g
optional_variable_pair = {
'optional_2': 2,
'optional_3': 3
}
f1 = f(1)
f2 = f(2)
calc_f1 = f1(**optional_variable_pair)
calc_f2 = f2(**optional_variable_pair)
If I'm reading your intent correctly, though, the essence of your question is wanting to pass new first arguments with the same successive arguments to a function. Depending on your use case, the wrapper function g may be unnecessary.
def f(arg1, *, optional_1=0, optional_2=0, optional_3=0):
return optional_1 + optional_2+optional_3
optional_variable_pair = {
'optional_2': 2,
'optional_3': 3
}
calc_f1 = f(1, **optional_variable_pair)
calc_f2 = f(2, **optional_variable_pair)
Obviously, if the first argument continues incrementing by one, a for loop is in order. Obviously, if you are never using the optional_1 parameter, you do not need to include it. But, moreover, if you find yourself using numbered arguments, there is a good chance you really should be working with tuple unpacking instead of keyword unpacking:
def f(*args):
return sum(args)
optional_variable_pair = (2, 3)
for i in range(1, 3):
calc = f(i, *optional_variable_pair)
# ...do something with calc...
You may also be interested in researching functools.partial, as well, which can take the place of your wrapper function g, and allow this:
import functools
def f(*args):
return sum(args)
f1 = functools.partial(f, 1)
f2 = functools.partial(f, 2)
calc_f1 = f1(2, 3) # = 1 + 2 + 3 = 6
calc_f2 = f2(2, 3) # = 2 + 2 + 3 = 7
You use key-value pairs as function argsuments, for this purpose you can use *args and **kwargs:
optional_variable_pair = {
"optional_1": 1,
"optional_2": 2,
"optional_3": 3,
}
calc_f1 = f1(**optional_variable_pair)
calc_f2 = f2(**optional_variable_pair)

Calling function with unknown number of parameters

I am trying to create a set of functions in python that will all do a similar operation on a set of inputs. All of the functions have one input parameter fixed and half of them also need a second parameter. For the sake of simplicity, below is a toy example with only two functions.
Now, I want, in my script, to run the appropriate function, depending on what the user input as a number. Here, the user is the random function (so the minimum example works). What I want to do is something like this:
def function_1(*args):
return args[0]
def function_2(*args):
return args[0] * args[1]
x = 10
y = 20
i = random.randint(1,2)
f = function_1 if i==1 else function_2
return_value = f(x,y)
And it works, but it seems messy to me. I would rather have function_1 defined as
def function_1(x):
return x
Another way would be to define
def function_1(x,y):
return x
But that leaves me with a dangling y parameter.
but that will not work as easily. Is my way the "proper" way of solving my problem or does there exist a better way?
There are couple of approaches here, all of them adding more boiler-plate code.
There is also this PEP which may be interesting to you.
But 'pythonic' way of doing it is not as elegant as usual function overloading due to the fact that functions are just class attributes.
So you can either go with function like that:
def foo(*args):
and then count how many args you've got which will be very broad but very flexible as well.
another approach is the default arguments:
def foo(first, second=None, third=None)
less flexible but easier to predict, and then lastly you can also use:
def foo(anything)
and detect the type of anything in your function acting accordingly.
Your monkey-patching example can work too, but it becomes more complex if you use it with class methods, and does make introspection tricky.
EDIT: Also, for your case you may want to keep the functions separate and write single 'dispatcher' function that will call appropriate function for you depending on the arguments, which is probably best solution considering above.
EDIT2: base on your comments I believe that following approach may work for you
def weigh_dispatcher(*args, **kwargs):
#decide which function to call base on args
if 'somethingspecial' in kwargs:
return weight2(*args, **kwargs)
def weight_prep(arg):
#common part here
def weight1(arg1, arg2):
weitht_prep(arg1)
#rest of the func
def weight2(arg1, arg2, arg3):
weitht_prep(arg1)
#rest of the func
alternatively you can move the common part into the dispatcher
You may also have a function with optional second argument:
def function_1(x, y = None):
if y != None:
return x + y
else:
return x
Here's the sample run:
>>> function_1(3)
3
>>> function_1(3, 4)
7
Or even optional multiple arguments! Check this out:
def function_2(x, *args):
return x + sum(args)
And the sample run:
>>> function_2(3)
3
>>> function_2(3, 4)
7
>>> function_2(3, 4, 5, 6, 7)
25
You may here refer to args as to list:
def function_3(x, *args):
if len(args) < 1:
return x
else:
return x + sum(args)
And the sample run:
>>> function_3(1,2,3,4,5)
15

Categories

Resources