Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tuples as function arguments

a tuple in python (in a code block) is defined by the commas; the parentheses are not mandatory (in the cases below). so these three are all equivalent:

a, b = 1, 2
a, b = (1, 2)
(a, b) = 1, 2

if i define a function

def f(a, b):
    print(a, b)

calling it this way will work:

f(2, 3)

this will not:

f((2, 3))
# TypeError: f() missing 1 required positional argument: 'b'

how does python treat tuples differently when they are function arguments? here the parentheses are necessary (i understand why this is the case and i am happy python works this way!).

my question is: how does python treat tuples differently when they are function arguments.

like image 984
hiro protagonist Avatar asked Jun 07 '19 17:06

hiro protagonist


People also ask

Can a function take a tuple as an argument?

A tuple can also be passed as a single argument to the function. Individual tuples as arguments are just individual variables. A function call is not an assignment statement; it's a reference mapping.

What is a tuple argument?

If a method accepts a tuple as an argument, that means it accepts multiple values. If a method returns a tuple, that means it returns multiple values. As an example, the Invoke() method in BindableFunction accepts a tuple as an argument, meaning it can accept multiple arguments.

Is there a tuple function in Python?

The Python tuple() function is a built-in function in Python that can be used to create a tuple. A tuple is an ordered and immutable sequence type.


3 Answers

For convenience, Python constructs a temporary tuple as needed for an assignment statement. Thus, all three of your assignment statements are exactly the same once they reach data movement.

A function call is not an assignment statement; it's a reference mapping. Therefore, the semantics are different.

If you want Python to unpack your tuple into two separate arguments, use the * operator:

f(*(2, 3))
like image 57
Prune Avatar answered Oct 04 '22 09:10

Prune


A tuple behaves like an immutable list. The fact that you notate them with parentheses is perhaps confusing, but it's more or less a coincidence - a result of the fact that parentheses are used for grouping things together and reducing ambiguity otherwise.

When you call a function, you're not providing a tuple. You're providing arguments. A tuple can be an argument, but only one - it's just a variable of type tuple.

What you can do is expand a tuple (or a list) into a a series of arguments with this notation:

tup = (2, 3)
f(*tup)
# expand the tuple (2,3) into a series of arguments 2, 3

You can do that with dictionaries as well, except with ** instead of *:

my_dict = {"arg1": 1, "arg2": 2}
f(arg1=my_dict["arg1"], arg2=my_dict["arg2"])
f(**my_dict)   # these are equivalent

On the other hand, functions can take arbitrary numbers of arguments (similar to how other languages do for printf() calls). For example:

def g(*args):
    print("I got this many arguments:", len(args))

Here, if you do type(args), you get tuple, and if you do type(*args), you get an error. This is because, in function headers, the * does the exact opposite: it packs the arguments that were given to the function into a single tuple, so that you can work with them. Consider the following:

g(2, 3)  # 2 arguments, both integers
g((2, 3)) # 1 argument, a tuple
g(*(2, 3)) # 2 arguments, both integers

In short,

  • functions are built in such a way that they take an arbitrary number of arguments
  • The * and ** operators are able to unpack tuples/lists/dicts into arguments on one end, and pack them on the other end
  • individual tuples/lists/dicts are otherwise just individual variables.
like image 32
Green Cloak Guy Avatar answered Oct 04 '22 07:10

Green Cloak Guy


The thing is that parens are used for several different things in Python -- for calling functions, for making tuples (it's not just the commas that matter, see the empty tuple ()), for changing evaluation priority in expressions.

In cases where interpreting them is ambiguous (e.g. your example f(2, 3) could be either a function call with two arguments, or a function call with one argument that is a tuple) the language has to make a choice.

If the Python parser was implemented so that it parsed this as a tuple, it would be impossible to have functions with more than one argument. If the Python parser was implemented so that it parsed this as two arguments, it's impossible to pass a literal tuple without the parens.

Clearly the first is a much bigger limitation, so the second was chosen.

Another example is with tuples with one element -- is (1+2) an expression yielding the number 3, or a tuple with one element, 3? Here if it was the second, then it would be impossible to use parens for expressing priority in an expression ((3+4)*5 vs 3+(4*5)). So it was decided to require the comma after the first element for 1-element tuples ((3,)).

like image 20
RemcoGerlich Avatar answered Oct 04 '22 08:10

RemcoGerlich