On 7/07/20 7:21 PM, Mike Dewhirst wrote:
-------- Original message --------

For comparison, here's the original form:-

>>> def f( a, *b, c=0 ):
...     print( a, type( a ) )
...     print( c, type( c ) )
...     print( b )
...
>>> f( 1, 'two', 3, 'four' )
1 <class 'int'>
0 <class 'int'>
('two', 3, 'four')


Shouldn't that def be ...

 >>> def f(a, c=0, *b):
???

It might appear that way, but in v3.7*, they are not:-

>>> def f(a, c=0, *b):
...     print( a, type( a ) )
...     print( c, type( c ) )
...     print( b, type( b ) )
...
>>> f( 1, 'two', 3, 'four' )
1 <class 'int'>
two <class 'str'>                #####
(3, 'four') <class 'tuple'>      #####

and even worse when we attempt to specify "c" as a keyword argument:

>>> f( 1, 'two', 3, c='four' )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for argument 'c'

>>> f( 1, c='four', 'two', 3 )
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument

>>> f( 1, 'four', 'two', 3 )
1 <class 'int'>
four <class 'str'>
('two', 3) <class 'tuple'>


Please remember also, that the idea of interposing a keyword-argument was by way of illustration. The original spec was to expand the API to accept either a series of scalars or equivalent values as a tuple, without (also) changing the API to require the new/tuple option be implemented as a keyword-argument.


However, to answer the question: the method of assigning the arguments' values to parameters is to start from the left, but upon reaching a *identifier to re-start by allocating from the right. This will leave zero or more values 'in the middle', to be tuple-ified as the *identifier.

Otherwise, if the allocation were l-to-r and "greedy", there would never be any values assigned to 'later' parameters!


For your reading pleasure:-

Python Reference Manual: 6.3.4. Calls
A 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


* I was remiss in not stating that this project is (?still) running with Python v3.7. Apologies! (it was established some time ago, and evidently the client has not seen fit to even consider upgrading as part of any sprint, to-date. Note to self...)

So, please be aware of:
https://docs.python.org/3/whatsnew/3.8.html#positional-only-parameters
https://www.python.org/dev/peps/pep-0570/


If you are running a more recent release, perhaps you might like to re-run the snippets, experiment, and document any contrary findings?
--
Regards =dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to