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