Pass one element of tuple as argument along with other arguments - python

I have a library function that returns a tuple and looks something like this
def some_function(some_string):
does something
return (text,id)
Now I want to pass the text returned from the some_function as argument to another function. The catch is the function has other arguments as well and I don't want to pass the entire tuple as a pointer. I also need need to retrieve many texts that will be generated by different values of some_string.
Depending on the condition met, I want to call another function which will look something like this
if abcd:
other_function(name,phone,**some_function("abcd")**,age)
elif xyz:
other_function(name,phone,**some_function("xyz")**,age)
else:
other_function(name,phone,**some_function("aaaa")**,age)
So what should I replace some_function("abcd") with so that it sends only the text and not both text and id as arguments?
The other_function is defined like this
def other_function(name,phone,text,age):
...
return
One solution that I came up with myself was to create another function that returns just the text.
def returntextonly(some_string):
self.some_string = some_string
(text,id) = some_function(some_string)
return text
and then call the other_function like
if abcd:
other_function(name,phone,returntextonly("abcd"),age)
I mostly program in C++ and have picked up python only recently. I was wondering if there is a better solution to the problem than creating a new function just to return one element of the tuple.
Thanks for reading.

You can run this as:
other_function(name, phone, some_function("abcd")[0], age)
There is no need to define the additional if statements, wrapper functions etc, since you want to pass only the first element of the tuple which is returned from the original function.
For the general case, this becomes:
other_function(name, phone, some_function(some_string)[0], age)
Note that the tuple is another (immutable) iterator, and its elements can be accessed using the regular indexes like in lists.

Related

when do we initialise a function call within the function vs as an argument?

I have a question about arguments in functions, in particular initialising an array or other data structure within the function call, like the following:
def helper(root, result = []):
...
My question is, what is the difference between the above vs. doing:
def helper(root):
result = []
I can see why this would be necessary if we were to run recursions, i.e. we would need to use the first case in some instances.
But are there any other instances, and am I right in saying it is necessary in some cases for recursion, or can we always use the latter instead?
Thanks
Python uses pointers for lists, so initializing a list or any other mutable objects in function definition is a bad idea.
The best way of doing it is like this:
def helper(root, result=None):
if isinstance(result, type(None)):
result = []
Now if you only pass one argument to the function, the "result" will be an empty list.
If you initiate the list within the function definition, by calling the function multiple times, "result" won't reset and it will keep the values from previous calls.

Is it possible to store a function and its arguments in a variable?

I have seen lots of information on storing functions in variables for execution, but the functions shown are always of the:
def foo():
print("Hello")
x = foo
x()
variety. Is it possible to store a function and its variables for later execution? I've currently worked around this by creating a tuple with the function as the first item and the variables as a nested tuple for the second item and then calling:
menu_input[KEY_D] = action_system.drop_item, (character,))
...LATER IN CODE...
for key in current_input:
if key in menu.menu_input.keys():
func, args = menu.menu_input[keys]
func(*args)
but I would really prefer to be able to store the function and its variables all together.
I would prefer to be able to store:
menu_input[KEY_D] = action_system.drop_item(character)
...LATER IN CODE...
for key in current_input:
if key in menu.menu_input.keys():
menu.menu_input[keys]()
because the function that handles menu input does not understand or care about the menu function itself, so it really doesn't need to see the input or care about the arguments passed.
Is this possible? If so, what am I missing? Sorry if this is obvious or obviously a bad idea--relatively new to python. If it is a terrible idea, I'd love to know why. I'm avoiding making this a class function of the menu item because I'm trying to work within an entity-component-system model where components store all data and the systems operate on them.
The functools.partial function is made for this purppose:
from functools import partial
menu_input[KEY_D] = partial(action_system.drop_item, character)
...
for key in current_input:
if key in menu.menu_input:
menu.menu_input[key]()
You could choose to use a lambda expression with no arguments.
def foo(value):
print(value)
x = lambda : foo("Hello")
x()

Can you store functions with parameters in a list and call them later in Python?

For example, when I have:
def function(text):
print(text)
mylist = [function('yes'),function('no')]
mylist[0]
It just prints yes and no and doesn't do anything with mylist[0].
I want it to be able to call the function with parameters in the list and not have the functions run when the program starts. Is this possible?
It sounds like you want to store the functions pre-bound with parameters. You can use functools.partial to give you a function with some or all of the parameters already defined:
from functools import partial
def f(text):
print(text)
mylist = [partial(f, 'yes'), partial(f,'no')]
mylist[0]()
# yes
mylist[1]()
# no
You can store functions as parameters, since functions in python are treated as first class citizens, which means you can effectively use them / treat them as you would a variable.
In your case, it isn't working because you're calling the function, not referencing the function.
mylist = [functionA,functionB]
mylist[0]('yes')
Here I've stored the references of the funcitons into a list, instead of calling them.
When you use (), you're effectively calling the function on the spot.
If you print mylist you will see that it contains None, which is the default return value of functions that don't have a return statement. You are, in fact, simply calling your function and saving the return value in a list.

Python — Passing Multiple Arguments

This works in the context of the lesson [Codecademy].
n = ["Michael", "Lieberman"]
# Add your function here
def join_strings(lst):
concat = ""
for string in lst:
concat += string
return concat
However, when I do this in regular Python, outside of the Codecademy environment, and I pass multiple arguments to the function, it returns an error. I was wondering how to make sure that the parameter of the function is a list. This way, I can pass however many arguments I want and the function will simply understand that this is a list.
Note, I do not want to do this with *args or something similar. I was simply wondering if there's a way to pass an actual list into a function.
Would you have to do something like a dictionary?
To pass a list to a function:
join_strings(["Michael", "Lieberman"])
Use asteric operator -
def join_strings(*lst):
Your function will interpret the positional parameters as list
You can pass the list as argument to the function for example in your program you can pass the list like this
n = ["Michael", "Lieberman"]
join_strings(n)
The above code passes list n to join_strings function
To check whether the passed argument is list or not you can have a checking condition like this
def join_strings(lst):
if isinstance(lst, list):
#do something
else:
# do something else
in the above code isinstance() method is used to check whether the passed argument is list or not
I’m sorry guys, apparently I did something wrong when I was typing it into the Terminal or something. Or possibly the way that Sublime (used to) interact with the pre-installed Python stuff on Mavericks. It works fine now, from Sublime and from the Terminal. I’m really not sure what the original problem was or where it was coming from.
— Typing the code in as I had it the first time gave me exactly what I wanted, and then I tweaked it to add a space between the concat strings.
def join_strings(lst):
concat = ""
for string in lst:
concat += (string + " ")
return concat
Thanks for all the help, though. Sorry to bother. :)

Passing arguments to functions in Python using inspect

I have a Python script which creates a dictionary of its own functions and I'd like it to execute them by reading in a function name and arguments using YARP (knowledge of YARP is irrelevant to this question though).
I create a list of strings called "inc" which is populated by values coming into the program. The first item is a function name, and any other strings in the list are arguments. I create a dictionary called "methods" where the key is the function name and the value is a reference to the function object (using the inspect module). I store the return value of the function in a variable "result".
The snippet below shows a simplified version of what I'm using so far, which works fine, but can't handle functions with more than one argument. To circumvent this I use a list if a function needs more parameters:
if len(inc) == 1:
result = methods[inc[0]]() # call method with 0 arguments
elif len(inc) == 2:
result = methods[inc[0]](inc[1]) # call method passing a string
else:
args = []
result = methods(inc[0])(inc[1:]) # call method passing a list
Ideally, I'd like to change this so that my functions can have any number of arguments, but I can't figure out how I can do this. I'm new to Python and I have looked at the documentation and various websites - I just can't find a solution. I've tried things like creating a tuple of the arguments, but that doesn't work either as it ends up passing the whole tuple in as one parameter.
Is there a better solution to this problem, like creating some kind of object which represents a set of parameters and passing that into the function? Any suggestions would be greatly appreciated!
You should check out https://stackoverflow.com/a/3394898/1395668.
The magic you are looking for is the *. Apply this to your list and it unpacks the items into the argument fields of your function:
a = [ 1, 2, 3]
def myfunc(a, b, c):
return a + b + c
print myfunc(*a)
Check out ** for the same approach for dict
It's a bit strange to have this kind of mixed structure:
inc = [func_name, arg1, arg2, ...]
Wouldn't it be much more natural to have two separate bits of information?
func_name = ...
args = [arg1, arg2, ...]
The you could do
methods[func_name](*args)
(Usually, I wouldn't bind the functions name to a variable, but preferably the function itself.)

Categories