[Python-ideas] Keyword only argument on function call

Steven D'Aprano steve at pearwood.info
Tue Sep 11 07:34:22 EDT 2018

On Tue, Sep 11, 2018 at 04:47:37AM +0000, Steve Barnes wrote:

> Couldn't just about all of the use cases mentioned so far be met in 
> quite a neat manner by providing access to a method, or dictionary, 
> called __params__ which would give access, as a dictionary, to the 
> parameters as supplied in the call, (or filled in by the defaults).

I imagine it would be fairly easy to fill in such a special __params__ 
local variable when the function is called. The interpreter already has 
to process the positional and keyword arguments, it probably wouldn't be 
that hard to add one more implicitly declared local and fill it in:

def function(spam, eggs, *args):
    print( __params__ )

function(2, 6, 99, 100)
# prints {'spam': 2, 'eggs': 6, '*args': (99, 100)}

But this has some problems:

(1) It might be cheap, but it's not free. Function calling in Python is 
already a minor bottleneck, having to populate one more local whether it 
is needed or not can only make it slower, not faster.

(2) It leads to the same gotchas as locals(). What happens if you assign 
to the __params__ dict? What happens when the parameters change their 
local value? The __param__ dict probably won't change.

(Like locals(), I expect that will depend on the interpreter.)

> If this was accessible externally, as fn.__defaults__ is then examples 
> such as:

Defaults are part of the function definition and are fixed when the 
function is created. The values assigned to parameters change every time 
you call the function, whether you need them or not. For non-trivial 
applications with many function calls, that's likely to add up to a 
measurable slow-down.

Its also going to suffer from race conditions, unless someone much 
cleverer than me can think of a way to avoid them which doesn't slow 
down function calls even more.

- I call function(a=1, b=2);

- function.__params__ is set to {'a': 1, 'b': 2}

- meanwhile another thread calls function(a=98, b=99);

- setting function.__params__ to {'a': 98, 'b': 99}

- and I then access function.__params__, getting the wrong values.

I think that __params__ as an implicitly created local variable is 
just barely justifiable, if you don't care about slowing down all 
function calls for the benefit of a tiny number of them. But exposing 
that information as an externally visible attribute of the function 
object is probably unworkable and unnecessary.


More information about the Python-ideas mailing list