[Python-ideas] About the passing the function arguments in Keyword form.

Eric V. Smith eric at trueblade.com
Mon Dec 24 11:30:59 EST 2018


On 12/24/2018 5:21 AM, 李默 wrote:
> I am having an idea on loosing the argument validity check when passing 
> the function arguments in keyword way.
> For example:
> -------------------------------
> deff(x, y):
> 
> print(x, y) def call_f(): f(x=7, y=9, z=9)
> 
> call_f()
> 
> ------------------------------
> 
> In the current of python, the extra pass of 'z' would let the 
> interpreter raise an exception and stop work. My idea is that the 
> interpreter need not stop because all the needed args are completely 
> provided. Of course for this toy example, 'f' can be define as f(x, y, 
> **kwargs) to achieve the same goal. However, essentially it is 
> reasonably to keep interpreter going as long as enough args are passed. 
> And this modification can bring more freedom of programming.
> 
> 
> Think about the following situations:
> 
> situation 1) there are many 'f's written by other people, and their args 
> are very similar and your job is to run each of them to get some results.
> 
> ---------------------
> 
> ##########code by others:
> 
> def f0(): ... def f1(x): ... def f2(x, y): ... def f3(x, y, z): ...
> 
> #if passing extra args are valid, you can run all the functions in the 
> following way, which is very compact and easy to read.
> 
> def test_universal_call():
> 
> funcs = [f0, f1, f2, f3] args = {'x':1, 'y':5, 'z':8} for f in funcs: 
> f(**args)
> 
> ------------------
> 
> 
> situation 2) there are several steps for make one product, each step is 
> in an individual function and needs different args.
> 
> ------------------
> 
> def make_oil(oil): ...
> 
> def make_water( water): ...
> 
> def make_powder(powder): ...
> 
> ## if passing extra args are valid, you can run all the functions in the 
> following way, which is very compact and easy to read.
> 
> def dish(): procedures = [make_oil, make_water, make_powder]
> 
> args = {'oil' : 1, 'water': 10, 'powder': 4} for f in procedures: f(**args)
> 
> 
> ---------------
> 
> 
> This idea is different from **kwargs. **kwargs are used when user wants 
> to record all the keywords passed. This idea is that even if the user 
> doesn’t want to record the arguments, that extra pass of keyword 
> arguments wont’t cause an exception.

I agree with other posters that we definitely do not want this as the 
default behavior in Python. However, it's also sometimes a useful 
pattern. I use it when I have a large plugin architecture that can take 
dozens or hundreds of possible parameters, but any given plugin is 
likely to only use a few parameters. I've written calllib 
(https://pypi.org/project/calllib/) to support this. It might achieve 
your goals.

This code:
-------------------
from calllib import apply

def f0():
     print('f0')

def f1(x):
     print(f'f1 {x!r}')

def f2(x, y):
     print(f'f2 {x!r} {y!r}')

def f3(x, y, z):
     print(f'f3 {x!r} {y!r} {z!r}')

def test_universal_call():
     funcs = [f0, f1, f2, f3]
     args = {'x':1, 'y':5, 'z':8}
     for f in funcs:
         apply(f, args)

test_universal_call()
-------------------
produces:
f0
f1 1
f2 1 5
f3 1 5 8

Eric


More information about the Python-ideas mailing list