RE: Tuple Comprehension ???
uot;", line 1, in sum([1, 2], [3,4]) TypeError: can only concatenate list (not "int") to list >>> sum([1, 2] + [3,4]) 10 Why? Because the plus sign asked the lists to combine into one larger list. The sum function is only called after python has combined the lists into one with no name. Now you can reasonably ask how to add a bunch of numbers, no lists or other gimmicks? Here is a short but working version: >>> def multiSum(*args): return sum(list(args)) ... >>> multiSum(1, 2, 3, 4 , 5) 15 Note I used an asterisk with a quite different meaning there in another sort of mini language you use to explain what you want function arguments to be seen as. *args there does not mean to do the expansion but the opposite and collect them into a single argument I can then make into a list. But guess what? args is already a list so this works just as well and since sum wants something like a list, it gets it: >>> def multiSum(*args): return sum(args) ... >>> multiSum(1, 2, 3, 4 , 5) 15 So although you can slow yourself down by trying to see how Python is like some other language, consider almost forgetting everything else you know and learn what python IS just for itself. I learned python after so many other languages that I would never have had time to master it if I kept comparing it to all the others. Having said that, many programming languages tend to converge in some ways and features in one are often adapted to or from another. There can be cognates. But my advice remains to learn what is expected from a function before using it and then you can adjust what you give it to match allowed configurations. Many languages have such needs and some of them do things differently. As an example, a language like R allows you to say do.call(func, list) which goes and calls func() with the expanded arguments taken from the list. Different idea for a related goal. Good luck. Learning can be mental fun when you have the fundamentals. -Original Message- From: Python-list On Behalf Of Hen Hanna Sent: Tuesday, February 21, 2023 8:52 PM To: python-list@python.org Subject: Re: Tuple Comprehension ??? On Tuesday, February 21, 2023 at 10:39:54 AM UTC-8, Thomas Passin wrote: > On 2/21/2023 12:32 PM, Axy via Python-list wrote: > > On 21/02/2023 04:13, Hen Hanna wrote: > >> > >> (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 ) > They **don't** have basically the same signature, though. max() takes > either an iterable or two or more numbers. Using max(*list_) presents > it with a series of numbers, so that's OK. > > sum() takes just one iterable (plus an optional start index). Using > sum(*list_) presents it with a series of numbers, and that does not > match its signature. > > Check what I said: > > >>> help(sum) > Help on built-in function sum in module builtins: > sum(iterable, /, start=0) > >>> help(max) thakns...i like the use of the word [signature] thanks for all the commetns... i'll try to catch up later. i think i understand it much better now. regular Python (func-calling) notation is like CL (Common Lisp) funcall. andfun( * args ) notation is like a (compile-time) macro ( max( * X )) macroexpand--->(apply maxX) ( max( * [1,2,3,4] ))macroexpand---> (apply max'(1 2 3 4) ) and Max() can take many arguments, but Sum() can basically take only 1. -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On 2/21/2023 8:52 PM, Hen Hanna wrote: On Tuesday, February 21, 2023 at 10:39:54 AM UTC-8, Thomas Passin wrote: On 2/21/2023 12:32 PM, Axy via Python-list wrote: On 21/02/2023 04:13, Hen Hanna wrote: (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 ) They **don't** have basically the same signature, though. max() takes either an iterable or two or more numbers. Using max(*list_) presents it with a series of numbers, so that's OK. sum() takes just one iterable (plus an optional start index). Using sum(*list_) presents it with a series of numbers, and that does not match its signature. Check what I said: help(sum) Help on built-in function sum in module builtins: sum(iterable, /, start=0) help(max) thakns...i like the use of the word [signature] thanks for all the commetns... i'll try to catch up later. i think i understand it much better now. regular Python (func-calling) notation is like CL (Common Lisp) funcall. andfun( * args ) notation is like a (compile-time) macro ( max( * X )) macroexpand--->(apply maxX) ( max( * [1,2,3,4] ))macroexpand---> (apply max'(1 2 3 4) ) and Max() can take many arguments, but Sum() can basically take only 1. ... and that one has to be an iterable. -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On Tuesday, February 21, 2023 at 10:39:54 AM UTC-8, Thomas Passin wrote: > On 2/21/2023 12:32 PM, Axy via Python-list wrote: > > On 21/02/2023 04:13, Hen Hanna wrote: > >> > >> (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 ) > They **don't** have basically the same signature, though. max() takes > either an iterable or two or more numbers. Using max(*list_) presents > it with a series of numbers, so that's OK. > > sum() takes just one iterable (plus an optional start index). Using > sum(*list_) presents it with a series of numbers, and that does not > match its signature. > > Check what I said: > > >>> help(sum) > Help on built-in function sum in module builtins: > sum(iterable, /, start=0) > >>> help(max) thakns...i like the use of the word [signature] thanks for all the commetns... i'll try to catch up later. i think i understand it much better now. regular Python (func-calling) notation is like CL (Common Lisp) funcall. andfun( * args ) notation is like a (compile-time) macro ( max( * X )) macroexpand--->(apply maxX) ( max( * [1,2,3,4] ))macroexpand---> (apply max'(1 2 3 4) ) and Max() can take many arguments, but Sum() can basically take only 1. -- https://mail.python.org/mailman/listinfo/python-list
RE: Tuple Comprehension ???
so on. When you view things that way, the design of max() and sum() may well make quite a bit more sense and also why they are not identically designed. -Original Message- From: Python-list On Behalf Of Axy via Python-list Sent: Tuesday, February 21, 2023 2:37 PM To: python-list@python.org Subject: Re: Tuple Comprehension ??? On 21/02/2023 19:11, avi.e.gr...@gmail.com wrote: > 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. I don't think overengineering is a good thing. Good design utilizes associativity so a person don't get amazed by inconsistency in things that expected to be similar. Axy. -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On 21/02/2023 19:11, avi.e.gr...@gmail.com wrote: 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. I don't think overengineering is a good thing. Good design utilizes associativity so a person don't get amazed by inconsistency in things that expected to be similar. Axy. -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On Tuesday, February 21, 2023 at 9:33:29 AM UTC-8, Axy wrote: > On 21/02/2023 04:13, Hen Hanna wrote: > > > > (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 ) > > > > > > > > i've been programming for many years... ( just new to Python ) > LOL, python is full of surprises. I'd definitely step into the same > piece of... Someday. > > Of course 'Builtin functions' section explains that, but the > inconsistency is weird. > > My response is absolutely useless, just two cents on the issue. Maybe > someone will fix that. > > Axy. i'm glad you get it ( that the inconsistency is weird. ) (1) print(1, sum( [1,2,3,4] )) (2) print(2, max( [1,2,3,4] )) (3) print(3, sum( * [1,2,3,4] )) (4) print(4, max( * [1,2,3,4] )) both 3,4 should be goodOR both 3,4 should be bad. that's what i think! ok i thnk i finally got it... (just before seeing Roel Schroeven's msg) -- https://mail.python.org/mailman/listinfo/python-list
RE: Tuple Comprehension ???
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 On Behalf Of Roel Schroeven Sent: Tuesday, February 21, 2023 1:11 PM To: python-list@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
Re: Tuple Comprehension ???
On 2/21/2023 12:32 PM, Axy via Python-list wrote: On 21/02/2023 04:13, Hen Hanna wrote: (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 ) They **don't** have basically the same signature, though. max() takes either an iterable or two or more numbers. Using max(*list_) presents it with a series of numbers, so that's OK. sum() takes just one iterable (plus an optional start index). Using sum(*list_) presents it with a series of numbers, and that does not match its signature. Check what I said: >>> help(sum) Help on built-in function sum in module builtins: sum(iterable, /, start=0) Return the sum of a 'start' value (default: 0) plus an iterable of numbers >>> help(max) Help on built-in function max in module builtins: max(...) max(iterable, *[, default=obj, key=func]) -> value max(arg1, arg2, *args, *[, key=func]) -> value Why they have different signatures may be lost to the whims of history and backwards compatibility... i've been programming for many years... ( just knew to Python ) LOL, python is full of surprises. I'd definitely step into the same piece of... Someday. Of course 'Builtin functions' section explains that, but the inconsistency is weird. My response is absolutely useless, just two cents on the issue. Maybe someone will fix that. Axy. -- https://mail.python.org/mailman/listinfo/python-list
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
RE: Tuple Comprehension ???
There is a very common misunderstanding by people learning python that a tuple has something to do with parentheses. It confused me too at first. A tuple is made by the use of one or more commas and no parentheses are needed except when, like everything else, they are used for grouping as in the arithmetic for (5 + 4) * 3 So (6) is not a tuple while a trailing comma makes (6,) to be a tuple with one entry. A tad confusingly is that () by itself is a tuple, containing nothing. While (,) is a syntax error! A serious design issue in most computer languages is that there are too few unique symbols to go around and some get re-used in multiple ways that usually are not ambiguous when viewed in context. As an example, sets and dictionaries both use curly braces but {} by itself is considered ambiguous and they chose to make it be an empty dictionary. To get an empty set, use set() instead. Parentheses are way overused and thus it gets murky at times as when they are used to sort of make it clear you are using a generator. Consider how this fails without parentheses: result = x*2 for x in [1,2,3] SyntaxError: invalid syntax But with parentheses works fine: result = (x*2 for x in [1,2,3]) result at 0x029A3CFCF030> However if you want a generator that is expanded into a list, you do not need the parentheses duplicated like this: result = list( (x*2 for x in [1,2,3]) ) and can just use this without nested parentheses: result = list( x*2 for x in [1,2,3] ) For completeness, you arguably should have a concept of a comprehension for every possible case but the people at python chose not to for reasons like the above and especially as it is fairly simple to use this version: result = tuple( x*2 for x in [1,2,3] ) Yes, it is a tad indirect and requires making a generator first. -Original Message- From: Python-list On Behalf Of Hen Hanna Sent: Monday, February 20, 2023 11:14 PM To: python-list@python.org Subject: Re: Tuple Comprehension ??? On Monday, February 20, 2023 at 7:57:14 PM UTC-8, Michael Torrie wrote: > On 2/20/23 20:36, Hen Hanna wrote: > > For a while, i've been curious about a [Tuple Comprehension] > I've never heard of a "Tuple comprehension." No such thing exists as > far as I know. > > So finally i tried it, and the result was a bit surprising... > > > > > > X= [ x for x in range(10) ] > > X= ( x for x in range(10) ) > > print(X) > > a= list(X) > > print(a) > What was surprising? Don't keep us in suspense! > > Using square brackets is a list comprehension. Using parenthesis > creates a generator expression. It is not a tuple. ok! LisX= [x for x in range(10) ] print( sum( LisX )) print( max( LisX )) print( sum( x for x in range(10) ) ) print( max( x for x in range(10) ) ) print( * LisX ) print( max( * LisX )) print( sum( LisX ))# same as before # print( sum( * LisX )) <--- Bad syntax !!! TypeError: sum() takes at most 2 arguments (10 given) _ (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 ) i've been programming for many years...( just knew to Python ) -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On 21/02/2023 04:13, Hen Hanna wrote: (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 ) i've been programming for many years...( just knew to Python ) LOL, python is full of surprises. I'd definitely step into the same piece of... Someday. Of course 'Builtin functions' section explains that, but the inconsistency is weird. My response is absolutely useless, just two cents on the issue. Maybe someone will fix that. Axy. -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On Monday, February 20, 2023 at 7:57:14 PM UTC-8, Michael Torrie wrote: > On 2/20/23 20:36, Hen Hanna wrote: > > For a while, i've been curious about a [Tuple Comprehension] > I've never heard of a "Tuple comprehension." No such thing exists as > far as I know. > > So finally i tried it, and the result was a bit surprising... > > > > > > X= [ x for x in range(10) ] > > X= ( x for x in range(10) ) > > print(X) > > a= list(X) > > print(a) > What was surprising? Don't keep us in suspense! > > Using square brackets is a list comprehension. Using parenthesis creates > a generator expression. It is not a tuple. ok! LisX= [x for x in range(10) ] print( sum( LisX )) print( max( LisX )) print( sum( x for x in range(10) ) ) print( max( x for x in range(10) ) ) print( * LisX ) print( max( * LisX )) print( sum( LisX ))# same as before # print( sum( * LisX )) <--- Bad syntax !!! TypeError: sum() takes at most 2 arguments (10 given) _ (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 ) i've been programming for many years...( just knew to Python ) -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On 20Feb2023 19:36, Hen Hanna wrote: For a while, i've been curious about a [Tuple Comprehension] So finally i tried it, and the result was a bit surprising... X= [ x for x in range(10) ] This is a list comprehension, resulting in a list as its result. X= ( x for x in range(10) ) This is not a tuple comprehension - Python does not have one. Instead, it is a generator expression: x for x in range(10) inside some brackets, which are just group as you might find in an expression like: (3 + 4) * 7 If you want a tuple, you need to write: X = tuple( x for x in range(10) ) which makes a tuple from an iterable (such as a list, but anything iterable will do). Here the iterable is the generator expression: x for x in range(10) Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
RE: Tuple Comprehension ???
Tuples are immutable and sort of have to be created all at once. This does not jive well wth being made incrementally in a comprehension. And, as noted, the use of parentheses I too many contexts means that what looks like a comprehension in parentheses is used instead as a generator. If you really want a tuple made using a comprehension, you have some options that are indirect. One is to create a list using the comprehension and copy/convert that into a tuple as in: mytuple = tuple( [x for x in range(10) ] ) I think an alternative is to use a generator in a similar way that keeps being iterated till done. mytuple = tuple( (x for x in range(10) ) ) And similarly, you can use a set comprehension and convert that to a tuple but only if nothing is repeated and perhaps order does not matter, albeit in recent python versions, I think it remains ordered by insertion order! mytuple = tuple( {x for x in range(10) } ) There are other more obscure and weird ways, of course but generally no need. Realistically, in many contexts, you do not have to store or use things in tuples, albeit some sticklers think it is a good idea to use a tuple when you want to make clear the data is to be immutable. There can be other benefits such as storage space used. And in many ways, tuples are supposed to be faster than lists. -Original Message- From: Python-list On Behalf Of Michael Torrie Sent: Monday, February 20, 2023 10:57 PM To: python-list@python.org Subject: Re: Tuple Comprehension ??? On 2/20/23 20:36, Hen Hanna wrote: > For a while, i've been curious about a [Tuple Comprehension] I've never heard of a "Tuple comprehension." No such thing exists as far as I know. > So finally i tried it, and the result was a bit surprising... > > > X= [ x for x in range(10) ] > X= ( x for x in range(10) ) > print(X) > a= list(X) > print(a) What was surprising? Don't keep us in suspense! Using square brackets is a list comprehension. Using parenthesis creates a generator expression. It is not a tuple. A generator expression can be perhaps thought of as a lazy list. Instead of computing each member ahead of time, it returns a generator object which, when iterated over, produces the members one at a time. This can be a tremendous optimization in terms of resource usage. See https://docs.python.org/3/reference/expressions.html#generator-expressions. Also you can search google for "generator expression" for other examples. -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Tuple Comprehension ???
On 2/20/23 20:36, Hen Hanna wrote: > For a while, i've been curious about a [Tuple Comprehension] I've never heard of a "Tuple comprehension." No such thing exists as far as I know. > So finally i tried it, and the result was a bit surprising... > > > X= [ x for x in range(10) ] > X= ( x for x in range(10) ) > print(X) > a= list(X) > print(a) What was surprising? Don't keep us in suspense! Using square brackets is a list comprehension. Using parenthesis creates a generator expression. It is not a tuple. A generator expression can be perhaps thought of as a lazy list. Instead of computing each member ahead of time, it returns a generator object which, when iterated over, produces the members one at a time. This can be a tremendous optimization in terms of resource usage. See https://docs.python.org/3/reference/expressions.html#generator-expressions. Also you can search google for "generator expression" for other examples. -- https://mail.python.org/mailman/listinfo/python-list
Tuple Comprehension ???
For a while, i've been curious about a [Tuple Comprehension] So finally i tried it, and the result was a bit surprising... X= [ x for x in range(10) ] X= ( x for x in range(10) ) print(X) a= list(X) print(a) -- https://mail.python.org/mailman/listinfo/python-list