Parameter List Chaining in Python

Python has great support for variable length parameter lists, you have optional parameters:

>>> def o(opt=1):
...   print opt
...
>>> o()
1
>>> o(2)
2
>>> o(opt=3)
3



then you have the one star for any number of parameters:

>>> def f(*params):
...   for p in params: # params is a list
...     print p
...
>>> f(1)
1
>>> f(1,2,3,4)
1
2
3
4


and you got two stars for keyword parameters:

>>> def g(**kws):
...   for item in kws.items(): # kws is a dict
...     print item
...
>>> g(one=1)
('one', 1)
>>> g(one=1, two=2, three=3)
('three', 3)
('two', 2)
('one', 1)


You can also use them together along with regular parameters and optional parameters as long as they follow the ordering: regular > optional > single star(varargs) > double star(keyword args):

>>> def h(req, opt=None, *params, **kws):
...   print 'req=', req
...   print 'opt=', opt
...   print 'params=', params
...   print 'kws=', kws
...
>>> h(1,2,3,4)
req= 1
opt= 2
params= (3, 4)
kws= {}
>>> h(1,two=2,three=3,four=4)
req= 1
opt= None
params= ()
kws= {'four': 4, 'two': 2, 'three': 3}
>>> h(1,two=2,three=3,opt=4)
req= 1
opt= 4
params= ()
kws= {'two': 2, 'three': 3}

If you have a handle on a list or a dict object, you can use it/them directly as the parameter list when you call a function:

>>> lst = [1,2,3]
>>> f(*lst)
1
2
3
>>> dct = dict(one=1,two=2,three=3)
>>> g(**dct)
('one', 1)
('three', 3)
('two', 2)


A techique I developed is to chain function calls lazily, sort of a poor man's partial function application. Say I have a function that takes a lot of optional parameters, let's say it generates a text field of some sort:

def textfield(label, name, size=10, classname='', id=None, 
    onclick=None, onkeypress=None):
    # blah


Now for my specific screen I want to specify a number of these parameters by default, and only vary the label and name parameters the rest of the way, so I do something like:

def tf(*params, **kws):
    textfield(size=20, classname='cool-field', *params, **kws)


now I can call it like this:

tf('Name', 'name')
tf('Birthdate', 'birthdate', onkeypress="checkBirthdate(this)")


The cool part about this is that I can add new optional parameters to textfield without having to change tf and yet still be able to use the new parameters from tf. I could have just as well use the partial function from the functional library, but this is pretty easy too.

blog comments powered by Disqus