[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