Why python doesn't use syntax like function(,,x) for default parameters?

Michal Kwiatkowski ruby at no.spam
Fri Mar 10 23:37:20 CET 2006


Dmitry Anikin napisał(a):
> Some example (from real life).
> def ChooseItems(StartDate, EndDate, Filter):
> #function returns a set of some items in chronological order
> #from required interval possibly using filter
> 
> ChooseItems() #get everything
> ChooseItems('01.01.2000', ,SomeFilter) #get everything after a date
> using filter
> ChooseItems(, '01.01.2000') #get everything before a date
> ChooseItems(, , SomeFilter) #get everything using filter
> 
> Now compare this to something which (I hope) is rather pythonian
> 
> Seq[:] #get everything
> Seq[2::3] #get everything after an index using filter (filter every
> third value)
> Seq[:3] #get everythin before an index
> Seq[::4] #get everything using a filter
> 
> Do you see any significant difference?

You're not comparing what you should. Range has only 3 parameters and is
a standard part of a language. Even if it's not obvious for someone
which parameters mean what in different combinations, it's not that hard
to look up in a manual. But user-defined functions are allowed to have
any number of arguments, with any possible meaning. That means it's
impossible to learn to recognize arguments exclusively by position
(which can be done for range), you have to look up function definition
*each time*.

And please remember that when writing a function, you define defaults as
values that user will mostly consider as appropriate. So if he doesn't
define them, that means he doesn't care. And Python syntax shows exactly
this intention. Your proposed syntax doesn't, as it suggest something
that user should know about is going on.

Now look at your example rewritten with standard Python keyword syntax.
If you know nothing about ChooseItems function, which version in your
opinion is more informative?

# get everything
ChooseItems()
# get everything after a date using filter
ChooseItems(after='01.01.2000', filter_with=SomeFilter)
# get everything before a date
ChooseItems(before='01.01.2000')
# get everything using filter
ChooseItems(filter_with=SomeFilter)

> I understand that many do not need such a syntax, I don't understand
> why someone would be AGAINST it. I don't propose to CHANGE anything
> in python (right now this syntax is error anyway). What I propose is just
> ADD another way of calling a function with keyword parameters but using
> POSITIONS instead of NAMES. And sometimes position is easier to
> remember than name. Anyway, who wants names let them use names.
> Who wants positions let them use positions. But to have a CHOICE is
> always good. As far as the choice itself doesn't damage anything,
> and I don't think that my does.

With this attitude Python will end up being Perl. Current semantics of
calling functions are already good enough to write clean and
understandable code.

> I think that if we compare
> ChooseItems('01.01.2000', ,SomeFilter)
> and
> ChooseItems(StartDate='01.01.2000', Filter=SomeFilter)
> the first one is more readable, 'cos you see
> what is meant right away. In second one you have to
> actually READ the keyword names to understand.
> It's not the common case, of course, but still, why
> not have a choice to use it?

I still think reading is better than guessing. :) Choosing good names
for arguments is another important factor (as shown in last example) in
readability.

> Some other examples which might benefit
> SetDate(year, month, day)
> SetDate(, month+1) # set next month, leaving year and day
> SetDate(, , 31) # set to end of month, not changing year
> #(wrong date adjusted automatically, of course)

In Poland we usually write dates in day-month-year notation. Having
function calls like this:

SetDate(year=y, month=m, day=d)
SetDate(month=m+1)
SetDate(day=31)

will be understandable by anyone.

> Please, don't try to scare me with 25-parameter functions.
> This is not for them. But to remember positions of two to
> five parameters is actually easier (if their order has some
> logic) then what are their names: startDate ? beginDate?
> firstDate? openDate? Date1?

I must disagree. If you choose argument names wisely you won't have any
trouble remembering which is which.

> The same approach can be used with tuples:
> (, , z) = func() # returning three element tuple()
> You think
> z = func()[2]
> is actually more clear? - By the way, I want THIRD value,
> not SECOND. And tuples don't have keyword names, do they?

It's not cleaner. It's error-prone, as you may lost one comma somewhere.
You also have to literally count what is the index of returned tuple
value that will be binded to "z".

> Finally, if syntax
> func (None, None, 10)
> seems natural to you, I propose to make it even more
> natural: I don't want some "None" passed as argument,
> I don't want anything at all passed, so I just use empty space
> func ( , , 10)
> And the called func don't have to bother with checking
> None for EACH argument but will happily use defaults instead.

If you would write it as func(third=10) it would be clearer that
func(, , 10) and called function will still behave as you expect
(without checking for None, but using defaults).

mk
-- 
 . o .       >>  http://joker.linuxstuff.pl  <<
 . . o   It's easier to get forgiveness for being wrong
 o o o   than forgiveness for being right.



More information about the Python-list mailing list