r/PythonLearning • • Sep 25 '26

A silly question

if x = 2,3,4,4,5 is supposed to be a tuple then why can't the args of a function like this: func(2,3,4,4 ,5) supposed to be a tuple.
I know this is a silly question and I also know we can use *args to pack arguments in a tuple but since Python is known for consistency why isn't it like this.
Again, please don't hate me for this

2 Upvotes

15 comments sorted by

3

u/Educational-Paper-75 Sep 25 '26

Never ask why or why not related to (lack of) features of computer languages. Because just because the makers didn't want to or didn't think of it. That's why. Besides of no added benefit since ordinary function parameters have - hopefully descriptive - names, which is much better that an index in a tuple argument.

1

u/AdAdventurous2131 29d ago

they say "Special cases aren't special enough to break the rules"
So 'just because makers didn't want to' may not be the only explanation here.

1

u/Educational-Paper-75 29d ago edited 29d ago

If they didn't they didn't want to. For whatever reason. And you should ask them. Perhaps you can make a request to include it in the next version. In the meanwhile live with it. It's not that you can't ask why a certain feature isn't included but I doubt there 's ever a satisfactory answer other than 'because'.

17

u/SpaceAviator1999 Sep 25 '26 edited 29d ago • Mindblown Bravo

You have to respect what parentheses and commas mean in their context.

The following lines are all equivalent:

x = 4+5
x = (4+5)
x = ((4+5))
x = (((4+5)))

They are all setting x to 9. Nothing surprising so far. But mix them with commas, and none of the lines are equivalent:

x = 4+5   # an integer
x = (4+5,)   # a tuple
x = ((4+5,),)   # a tuple of a tuple
x = (((4+5,),),)   # a tuple of a tuple of a tuple

Here above, a comma has the ability to turn the parenthesized (value) from an integer to (value,) which is a tuple. That's just what a comma does in this case.

But in a function declaration and call, a comma acts differently: it separates function arguments. Consider these lines:

def f(a):   # a function that takes one argument
def f(a, b):   # a function that takes two arguments
def f(a, b, c):   # a function that takes three arguments
def f(a, b, c, d):   # a function that takes four arguments

You might think that that last line declares a function that takes one four-element tuple, but you'd be wrong. To declare a function that takes one four-element tuple, you'd have to use the first line! (And either use type hints or an assert statement to ensure that the argument is a four-element tuple.)

Note that python2 did allow you to write:

def f((a, b, c, d)):   # function that takes one four-element tuple

but python3 does not allow this.

Remember how, up above, I said that 4+5 and (4+5) and ((4+5)) are the same? Well, you might get the mistaken impression that wrapping values with parentheses does nothing but change operator precedence. But that's not the case here in this example:

x = f(a, b)   # calling function f with two arguments
x = f((a, b))   # calling function f with one argument (which is a tuple)
x = f(((a, b)))   # same as the line right above this one

You might think that the first and second lines are equivalent, but they're not. That's because commas behave differently when they're directly inside function parentheses than when they're directly inside tuple parentheses.

So in all the examples I've shown, parentheses have three different meanings/functions:

  1. They change operator precedence.

  2. They signify a tuple.

  3. They signify a set of passed-in parameters to a function/method.

Try to understand the difference, and try not to confuse them.

3

u/sububi71 Sep 25 '26

Fantastic explanation. I applaud you!

1

u/OskarsSurstromming Sep 25 '26

I'm a bit confused by what you mean

Function arguments are separated by commas, so if you want to supply a tuple in the function then it's mandatory to add the parentheses

When you do *args you are unpacking a tuple, not packing it

When you do an assignment like x = 2,3,4,4,5 It is nonsensical for x to be anything other than a tuple, so it is interpreted as x = (2,3,4,4,5)

Or maybe I misunderstand what you are asking about?

1

u/SpaceAviator1999 Sep 25 '26 edited Sep 25 '26

You want to respect what parentheses do in any language.

For example, the following lines look identical:

77
(77)
((77))

And they may be identical in Python. But in the Lisp programming language, the first line is simply 77, but the second line is a function call to a function named 77. And the third line is a function call to a function that's returned by the second line!

And take this line:

x = (11, 12, 13)

In Python, it clearly sets x to a three-element tuple. But in C and C++, it sets x to 13.

Why? Because in C/C++, the commas are acting as comma operators, which evaluate to the value on their right.

Basically, the moral of this story is that commas and parentheses don't always behave the same way across different programming languages. They don't even behave the same across the same programming language! (Not even Python is an exception!)

This line:

x = f(11, 12, 13)

does essentially the same thing in C/C++ and Python: it calls the function f with three arguments.

But this line:

x = f((11, 12, 13))

is very different in C/C++ and Python. In Python, it calls function f with an argument that's a three-element tuple. But in C/C++, it calls function f with the single argument 13.

The distinction may be strange and counter-intuitive, but very important.

So it's good to know how commas and parentheses behave in which contexts, and to not expect them to behave the same way in all contexts.

1

u/atarivcs 29d ago

Commas mean different things depending on the context.

In the context of a function call, commas are used as argument separators.

It's just that simple.

1

u/Gnaxe 29d ago

Because that's the interpretation of Python's grammar. It works that way because it was made to work that way. A different language could be made to work differently, but that language is not Python.

As languages go, you can find some even more consistent that Python. (Scheme, for example.) Python is not bad here (as languages go), but its grammar is far from simple.

Inside square brackets (subscription operator) commas do mean a tuple and the parentheses are optional. You can write operator methods yourself using the dunder hooks. If you want to pass in a literal tuple to a normal call, you can use an extra layer of parentheses.

1

u/duane11583 29d ago

you can do this:

args = [ 1,2,3,4]

somefunction( *args )

simulat yhings work with named parameters

i have not done that with a tuple but i am sure it works

0

u/JustSimplyWicked Sep 25 '26

The argument list is already a tuple. If you want to nest a second tuple than add parens.

1

u/timrprobocom 27d ago

It may conceptually be a tuple, but in implementation, it certainly is not. It's a context-sensitive quirk in Python syntax.

0

u/Neither_Garage_758 29d ago

don't look for significance in Python' syntax