HH, Just FYI, as a seeming newcomer to Python, there is a forum that may fit some of your questions better as it is for sort of tutoring and related purposes:
https://mail.python.org/mailman/listinfo/tutor I am not discouraging you from posting here, just maybe not to overwhelm this group with many questions and especially very basic ones. Your choice. But what I read below seems like an attempt by you to look for a cognate to a python feature in a LISP dialect. There may be one but in many ways the languages differ quite a bit. As I see it, using the asterisk the way you tried is not all that common and you are sometimes using it where it is not needed. Python is NOT a language that is strongly typed so there is no need to take a list or other iterator or container of numbers and fool the interpreter into making it look like you placed them as multiple arguments. In many places, just handing over a list is fine and it is expanded and used as needed. When a function like sum() or max() is happy to take a single list argument, then feed it the list, not *list. Where it can be helpful is a function like range() where range() takes up to three arguments as in: >>> list(range(7)) [0, 1, 2, 3, 4, 5, 6] >>> list(range(11, 20)) [11, 12, 13, 14, 15, 16, 17, 18, 19] >>> list(range(31, 45, 3)) [31, 34, 37, 40, 43] In the above, you are really asking for stop=num, or start/stop or start/stop/step. But what if you have some data structure like a list that contains [31, 45, 3] or just a two number version or a single number and it is sitting in a variable. You can ask Python to unpack all kinds of things in various ways and the asterisk is one simple one. Unpacking is itself a huge topic I will not discuss. >>> mylist = [31, 45, 3] >>> list(range(mylist)) Traceback (most recent call last): File "<pyshell#57>", line 1, in <module> list(range(mylist)) TypeError: 'list' object cannot be interpreted as an integer >>> list(range(*mylist)) [31, 34, 37, 40, 43] Range() takes only something like integers. So you use the * in this context to give it three integers individually. Range does not take named arguments but many other functions do. So what if I have an arbitrary function that accepts arguments like myfunc(alpha=default, beta=default, gamma=default) where the defaults are not the issue and may be anything such as "" or 0 or an empty set. I could write code like this that creates a toy version of the function and create a dictionary that supplies any combination of the required arguments and use not the * operator that expands something like a list, but the doubled ** operator that expands all entries of a dictionary into individual items: >>> def myfunc(alpha=1, beta="", gamma=""): ... print(f"alpha={alpha}, beta={beta}, gamma={gamma}") ... ... >>> myfunc() alpha=1, beta=, gamma= >>> myfunc(1, 2, 3) alpha=1, beta=2, gamma=3 >>> mydict = { "alpha" : 101, "beta" : "hello", "gamma" : "buy bye" } >>> mydict {'alpha': 101, 'beta': 'hello', 'gamma': 'buy bye'} >>> myfunc( **mydict ) alpha=101, beta=hello, gamma=buy bye I have no idea if any of this is really like your macroexpand. It does not need to be. It is what it is. If you went back to a language like C, their macros might be used to make a "constant with "#define" but they would not be a constant in the same way as a language that uses a keyword that makes a variable name into a constant that cannot be changed without causing an error. Similar but also not the same. This is only the surface of some things commonly done in python when it makes sense. But often there is no need and your examples are a good example when the function happily take a list in the first place. So why fight it especially when your expanded version is not happily received? The takeaway is that you need to read a bit more of a textbook approach that explains things and not use slightly more advanced features blindly. It is NOT that sum() takes a single argument that matters. It fails on something like sum(1) which is a single argument as well as sum("nonsense") and so on. What sum takes is a wide variety of things in python which implement what it takes to be considered an iterable. And it takes exactly one of them under the current design. sum((1,)) 1 sum([1]) 1 sum(n- 5 for n in range(10,15)) 35 All kinds of things work. Tuples and lists are merely the easiest to see. The latter exmple is a generator that returns 5 less than whatever range() produces as another kind of iterable. The sum() function will not take two or more things, iterable or not. So the first below fails and the second does not: >>> sum([1, 2], [3,4]) Traceback (most recent call last): File "<pyshell#94>", line 1, in <module> 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 <python-list-bounces+avi.e.gross=gmail....@python.org> 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. and fun( * args ) notation is like a (compile-time) macro ( max( * X )) ----macroexpand---> (apply max X) ( 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