-------- Original message --------From: dn via Python-list 
<python-list@python.org> Date: 7/7/20  16:04  (GMT+10:00) To: 'Python' 
<python-list@python.org> Subject: Questioning the effects of multiple 
assignment TLDR; if you are a Python 'Master' then feel free to skim the first 
part (which you should know hands-down), until the excerpts from 'the manual' 
and from there I'll be interested in learning from you...Yesterday I asked a 
junior prog to expand an __init__() to accept either a series of (>1) scalars 
(as it does now), or to take similar values but presented as a tuple. He was a 
bit concerned that I didn't want to introduce a (separate) keyword-argument, 
until 'we' remembered starred-parameters. He then set about experimenting. 
Here's a dichotomy that surfaced as part of our 'play':-(my problem is: I can't 
(reasonably) answer his question...)If you read this code:NB The print-ing does 
not follow the input-sequence, because that's the point to be made... >>> def 
f( a, *b, c=0 ):Shouldn't that def be ...>>> def f(a, c=0, *b):???...     
print( a, type( a ) )...     print( c, type( c ) )...     print( b )... >>> f( 
1, 'two', 3, 'four' )[I had to force "c" to become a keyword argument, but 
other than that, we'll be using these three parameters and four 
argument-values, again]Question 1: did you correctly predict the output?1 
<class 'int'>0 <class 'int'>('two', 3, 'four')Ahah, "c" went to default because 
there was no way to identify when the "*b" 'stopped' and "c" started - so all 
the values 'went' to become "b" (were all "consumed by"...).Why did I also 
print "b" differently?Building tension!Please read on, gentle reader...Let's 
make two small changes:- amend the last line of the function to be similar:...  
   print( b, type( b ) )- make proper use of the function's API: >>> f( 1, 
'two', 3, c='four' )Question 2: can you predict the output of "a"? Well 
duh!(same as before)1 <class 'int'>Question 3: has your predicted output of "c" 
changed? Yes? Good!(Web.Refs below, explain; should you wish...)four <class 
'str'>Question 4: can you correctly predict the content of "b" and its 
type?('two', 3) <class 'tuple'>That makes sense, doesn't it? The arguments were 
presented to the function as a tuple, and those not assigned to a scalar value 
("a" and "c") were kept as a tuple when assigned to "b".Jolly good show, 
chaps!(which made my young(er) colleague very happy, because now he could see 
that by checking the length of the parameter, such would reveal if the 
arguments were being passed as scalars or as a tuple.Aside: however, it made me 
think how handy it would be if the newly-drafted PEP 622 -- Structural Pattern 
Matching were available today (proposed for v3.10, 
https://www.python.org/dev/peps/pep-0622/) because (YAGNI-aside) we could then 
more-easily empower the API to accept other/more collections!Why am I writing 
then?Because during the same conversations I was 
'demonstrating'/training/playing with some code that is (apparently) very 
similar - and yet, it's not. Oops!Sticking with the same, toy-data, let's code: 
>>> a, *b, c = 1, 'two', 3, 'four' >>> a, type( a ) >>> c, type( c ) >>> b, 
type( b )Question 5: what do you expect "a" and "c" to deliver in this 
context?(1, <class 'int'>)('four', <class 'str'>)Happy so far?Question 6: (for 
maximum effect, re-read snippets from above, then) what do you expect from 
"b"?(['two', 3], <class 'list'>)List? A list? What's this "list" stuff???When 
"b" was a parameter (above) it was assigned a tuple!Are you as shocked as 
I?Have you learned something?(will it ever be useful?)Has the world stopped 
turning?Can you explain why these two (apparently) logical assignment processes 
have been designed to realise different result-objects?NB The list cf tuple 
difference is 'legal' - at least in the sense that it is documented/expected 
behavior:-Python Reference Manual: 7.2. Assignment statementsAssignment 
statements are used to (re)bind names to values and to modify attributes or 
items of mutable objects:...An assignment statement evaluates the expression 
list (remember that this can be a single expression or a comma-separated list, 
the latter yielding a tuple) and assigns the single resulting object to each of 
the target lists, from left to right....A list of the remaining items in the 
iterable is then assigned to the starred target (the list can be 
empty).https://docs.python.org/3/reference/simple_stmts.html#assignment-statementsPython
 Reference Manual: 6.3.4. CallsA call calls a callable object (e.g., a 
function) with a possibly empty series of arguments:...If 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).https://docs.python.org/dev/reference/expressions.html#calls-- 
Regards,=dn-- https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to