[Tutor] don't understand iteration

Alan Gauld alan.gauld at btinternet.com
Tue Nov 11 02:06:50 CET 2014


On 11/11/14 00:28, Clayton Kirkwood wrote:


> This seems to be the only relevant words:
> 4.7.4. Unpacking Argument Lists
>
> ...when the arguments are already in a list or tuple but need to be unpacked
 > > for a function call .... If they are not available separately, 
write the function
 > call with the *-operator to unpack the arguments
 > out of a list or tuple:

>>>> list(range(*args))            # call with arguments unpacked from a list
> [3, 4, 5]

So it tells you that when you need to extract the arguments out of a 
list or tuple use the * operator and it gives an example of unpacking 
the list [3,6] (ie. args) when using the range() function.

> I fail to see the reference to '* list' except for possibly the '*-operator',

That's the one.

> for which there is no example

There is, the one above using it in range()

>  later the reference to '*args' which appears to act as a
 > wildcard/expander/replacement for the more exacting [3,6].

Its not a wild card but it is an expander. it says "unpack
the sequence and treat the members as individual values"

> I saw something like a '*list' was way off in PyObject and daughters
 > suggesting a C char * or pointer.

pointers in C are unrelated. Thankfully...

> I'm sure I don't need to get into that just to find a reference
 > to something so obvious as a '*list',

> something that I run across all of the time.

Oddly I don't see it that often. but I'd agree its not a totally
rare feature, just not an every day one. Which is why it gets a
passing coverage in the tutorial.

For (slightly) more detail you can read the language reference:

https://docs.python.org/3/reference/compound_stmts.html#function-definitions

Where it says:
-----------
Function call semantics are described in more detail in section Calls. A 
function call always assigns values to all parameters mentioned in the 
parameter list, either from position arguments, from keyword arguments, 
or from default values. If the form “*identifier” is present, it is 
initialized to a tuple receiving any excess positional parameters, 
defaulting to the empty tuple. If the form “**identifier” is present, it 
is initialized to a new dictionary receiving any excess keyword 
arguments, defaulting to a new empty dictionary. Parameters after “*” or 
“*identifier” are keyword-only parameters and may only be passed used 
keyword arguments.
------------

And the link to Calls:

https://docs.python.org/3/reference/expressions.html#calls

which says:
--------------
f there are more positional arguments than there are formal parameter 
slots, a TypeError exception is raised, unless a formal parameter using 
the syntax *identifier is present; in this case, that formal parameter 
receives a tuple containing the excess positional arguments (or an empty 
tuple if there were no excess positional arguments).

If any keyword argument does not correspond to a formal parameter name, 
a TypeError exception is raised, unless a formal parameter using the 
syntax **identifier is present; in this case, that formal parameter 
receives a dictionary containing the excess keyword arguments (using the 
keywords as keys and the argument values as corresponding values), or a 
(new) empty dictionary if there were no excess keyword arguments.

If the syntax *expression appears in the function call, expression must 
evaluate to an iterable. Elements from this iterable are treated as if 
they were additional positional arguments; if there are positional 
arguments x1, ..., xN, and expression evaluates to a sequence y1, ..., 
yM, this is equivalent to a call with M+N positional arguments x1, ..., 
xN, y1, ..., yM.

A consequence of this is that although the *expression syntax may appear 
after some keyword arguments, it is processed before the keyword 
arguments (and the **expression argument, if any – see below). So:
 >>>
 >>> def f(a, b):
...  print(a, b)
...
 >>> f(b=1, *(2,))
2 1
 >>> f(a=1, *(2,))
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
TypeError: f() got multiple values for keyword argument 'a'
 >>> f(1, *(2,))
1 2

It is unusual for both keyword arguments and the *expression syntax to 
be used in the same call, so in practice this confusion does not arise.

If the syntax **expression appears in the function call, expression must 
evaluate to a mapping, the contents of which are treated as additional 
keyword arguments. In the case of a keyword appearing in both expression 
and as an explicit keyword argument, a TypeError exception is raised.

Formal parameters using the syntax *identifier or **identifier cannot be 
used as positional argument slots or as keyword argument names.

----------------------



Which may or may not help! :-)

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos



More information about the Tutor mailing list