A more appropriate way of saying this is: there is always exactly 0 or 1
argument. When there appear to be more, there really is a single argument
which happens to be a tuple. You have more or less discovered this.
The exception for 0 arguments is unfortunate. I have played with the
thought of making f() and f(()) equivalent, but... there is a complication
with class methods. When C is a class defining a method m with argument
list (self, args), and c an instance of C, then calling c.m(x) is equivalent
C.m(c, x). However, argument-less methods are conventionally defined as
m(self), and here c.m() is equivalent to C.m(c). If f() and f(()) were to
be equivalent, all argument-less methods would have to be rewritten to
require a second argument, which would always receive the value ().
(Part of all this is caused by the notion that there is *nothing special*
about a method in the way you declare it; purely the fact that a class
attribute happens to be a function object makes it a method. This
simplifies life in several other places, and gives a nice way of
constructing a class out of existing functions.)
A different approach would appear to *always* make function arguments a
tuple. This would pass single arguments as singleton tuples, making f(1)
equivalent to f(1,). However, this doesn't fly: in the current situation,
you can write x = (1,2,3) and later call f(x) with exactly the same result
as f(1,2,3). In the alternate approach, f(x) would be turned into f(x,),
and would no longer be equivalent to f(1,2,3). So either way you lose.
Knowing the argument structure of the called function would also be a
possibility, but this definitely has to be done at run-time (when the call
is executed), not at "compile-time" (when it is parsed and turned into
internal opcodes), since there is also a (desirable!) equivalence between
a, b = x
"use a and b"
def f(a, b):
"use a and b"
So it seems we're stuck. The most realistic solution in my eyes is to
require methods to always have exactly two arguments, the second one
receiving a dummy () value in case of argument-less methods, but this cannot
be introduced without breaking old code. (Is there any old code outside my
own that uses this? I'm always willing to change the language if it breaks
nobody's code but mine -- including the library).
--Guido van Rossum, CWI, Amsterdam <email@example.com>
"I'm sorry, is this a five-minute argument, or the full half-hour?"