Tuple Comprehension ???

avi.e.gross at gmail.com avi.e.gross at gmail.com
Tue Feb 21 14:11:38 EST 2023


There are limits to anyone arguing for designs to be the way they want or expect and Roel has explained this one below.

When it comes to designing a function, lots of rules people expect are beyond irrelevant. Many functions can be implemented truly hundreds of ways with varying numbers of arguments and defaults and other effects. I can make a function that raises the first argument to a power specified in the second argument with no defaults and you get a syntax error for calling it with one argument or more than two arguments. Or I can make the second argument use a keyword with a default of 1, or 2 or whatever I wish and it can now be called with one argument to get the default or two but not more. Or, I can have the function absorb all additional arguments and ignore them or even use them as additional powers to be raised to so pow(2, 3, 4, 5) returns a tuple or list of 8, 16, 32.  Or maybe not and it would return ((2^3)^4)^5 or any other nonsense you design.

There IS NO CONSISTENCY possible in many cases unless you make a family of similarly named functions and add some thing to each name to make it clear.

Python arguably is harder than some languages in this regard as it allows way more flexibility. If a function accepts an iterator, and another does not, the call may superficially looks the same but is not. 

So, yes, max() could have been designed differently and you can even design your own mymax() and mysum() to check the arguments they receive and re-arrange them in a way that lets you call the original max/sum functions potentially in the same ways. 

But as a general rule, when using a function, don't GUESS what it does or infer what it does and then complain when someone says you should have read the manual. There are too many design choices, often done by different programmers and often motivated by ideas like efficiency. You likely can not guess many of them.

And lots of python functions you write can make use of all kinds of features such as caching results of previous computations or holding on to variables such as what you asked for last time so it can be used as a default. If I write a function like go(direction=something, distance=something) then perhaps my design will remember the last time it was invoked and if you call it again with no arguments, it may repeat the same action, or if only one is given, the other is repeated. But on a first call, it may fail as it has no memory yet of what you did. That may be intuitive to some and not others, but would it make as much sense for another function to be designed the same way so it tolerates being called with no arguments when this makes less sense? Do I often want to call for sin(x) and later for just sin() and expect it to mean that it be repeated?

But back to the original question about max/sum it gets weirder. Although max() takes any number of arguments, it really doesn't. There is no way to get the maximum of a single argument as in max(5) because it is designed to EITHER take one iterable OR more than one regular argument. 

So one case that normally fails is max([]) or any empty iterable and you can keep it from failing with something like max([], default=0) .

In your own code, you may want to either design your own functions, or use them as documented or perhaps create your own wrapper functions that carefully examine what you ask them to do and re-arrange as needed to call the function(s) you want as needed or return their own values or better error messages.  As a silly example, this fails:

max(1, "hello")

Max expects all arguments to be of compatible types. You could write your own function called charMax() that converts all arguments to be of type str before calling max() or maybe call max(... , key=mycompare) where compare as a function handles this case well.

The key point is that you need to adapt yourself to what some function you want to use offers, not expect the language to flip around at this point and start doing it your way and probably breaking many existing programs.

Yes, consistency is a good goal. Reality is a better goal.




-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com at python.org> On Behalf Of Roel Schroeven
Sent: Tuesday, February 21, 2023 1:11 PM
To: python-list at python.org
Subject: Re: Tuple Comprehension ???

Hen Hanna schreef op 21/02/2023 om 5:13:
>                  (A)   print( max( * LisX ))
>                  (B)   print( sum( * LisX ))        <------- Bad syntax !!!
>
> What's most surprising is....     (A)  is ok, and  (B) is not.
>
>             even tho'   max() and sum()  have   (basically)  the same syntax...  ( takes one arg ,  whch is a list )
>
There's an important difference in syntax.

sum() takes an iterable:

sum(iterable, /, start=0)
     Return the sum of a 'start' value (default: 0) plus an iterable of numbers

     When the iterable is empty, return the start value.
     This function is intended specifically for use with numeric values and may
     reject non-numeric types.

max() on the other hand takes either an iterable or a number of individual elements:

max(...)
     max(iterable, *[, default=obj, key=func]) -> value
     max(arg1, arg2, *args, *[, key=func]) -> value

     With a single iterable argument, return its biggest item. The
     default keyword-only argument specifies an object to return if
     the provided iterable is empty.
     With two or more arguments, return the largest argument.

That second form of max is why max(*some_list) works while
sum(*some_list) doesn't.

--
"You can fool some of the people all the time, and all of the people some of the time, but you cannot fool all of the people all of the time."
         -- Abraham Lincoln
"You can fool too many of the people too much of the time."
         -- James Thurber

--
https://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list