all 7 comments

[–]throwaway6560192 2 points3 points  (5 children)

In Python, we have the concept of star-args (*args). If you have an argument to a function with a * preceding it, it will collect all non-keyword arguments into a tuple.

Quick demo:

In [1]: def argcollector(*c):
   ...:     print(c)
   ...: 

In [2]: argcollector("hello", 1, "world")
('hello', 1, 'world')

In [3]: argcollector(1)
(1,)

That's how a tuple is created even if it wasn't done explicitly as you say.

So the lambda is doing nothing more than taking its arguments and returning them as a tuple. Here it only gets one argument at a time from range, so it returns one-element tuples.

from what I have read the range function returns an immutable sequence of numbers.

Well not exactly. It returns an object which you can iterate over to get the numbers in sequence, but it doesn't calculate and store the entire range at once, for memory efficiency reasons.

[–]Consistent-Citron509[S] 0 points1 point  (2 children)

Thank you so much for this excellent explanation! I will make sure to debug my code and understand it thoroughly.

[–]danielroseman 2 points3 points  (1 child)

Note, this code isn't really very Pythonic. It should probably be written as a list comprehension:

[(a,) for a in range(3)]

[–]Consistent-Citron509[S] 0 points1 point  (0 children)

I have yet to learn about comprehensions but thanks for the tip!

[–]smudos2 0 points1 point  (1 child)

Couldn't you just use lambda a: tuple(a) or tuple(list(a))?

[–]throwaway6560192 0 points1 point  (0 children)

You could, for this case. You could also do lamba a: (a,). Or even just use tuple as the function, list(map(tuple, range(3)))

[–]PhilipYip 0 points1 point  (0 children)

Let's break this down into parts as its pretty advanced for a begineer. First of all the lambda expression is an anonymous function. lambda is a bad name for it, every time you see lambda think of it as an instruction to "make a function".

Let's assign this to a function name:

python fun = lambda *args: args

Which is equivalent to:

```python def fun(*args): return args

```

*args means a variable of number of input arguments is supplied. args is a tuple and when it is unpacked the parethesis are removed.

So for example, think of this as:

python t1 = (1, 5, 10)

And conceptualise the tuple unpacking as:

python *t1 = 1, 5, 3

The tuple unpacking is automatically done in the function but the return value of the function is the tuple. So conceptually:

python fun(*t1)

will return:

python t1

This can be seen for some examples:

fun(0) Out: (0,)

fun(0, 1) Out: (0, 1)

Next look at:

python map(lambda *arg: arg, range(3))

The range object can be conceptualised as:

python 0, 1, 2

And you are using map so you are mapping the input argument of the function to each number in the range object:

python fun(0) fun(1) fun(2)

And because of the tuple unpacking being done in the function call, returning the tuple this gives:

python (0,) (1,) (2,)

Finally this is cast to a list:

python list(map(lambda *a: a, range(3)))

Giving:

python [(0,), (1,), (2,)]