On Tue, Jul 7, 2020 at 2:30 AM Mike Dewhirst <mi...@dewhirst.com.au> wrote:
> > -------- 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 > -- > Dunno about the rest of the list but I'm finding this message incredibly hard to read. Please sir - - - - would you please break up your message into at least sentences? Regards -- https://mail.python.org/mailman/listinfo/python-list