Variable arguments (*args, **kwargs): seeking elegance

Peter Cacioppi peter.cacioppi at gmail.com
Sun Oct 6 17:34:57 EDT 2013


On Saturday, October 5, 2013 9:04:25 PM UTC-7, John Ladasky wrote:
> Hi folks,
> 
> 
> 
> I'm trying to make some of Python class definitions behave like the ones I find in professional packages, such as Matplotlib.  A Matplotlib class can often have a very large number of arguments -- some of which may be optional, some of which will assume default values if the user does not override them, etc.
> 
> 
> 
> I have working code which does this kind of thing.  I define required arguments and their default values as a class attribute, in an OrderedDict, so that I can match up defaults, in order, with *args.  I'm using set.issuperset() to see if an argument passed in **kwargs conflicts with one which was passed in *args.  I use  set.isdisjoint() to look for arguments in **kwargs which are not expected by the class definition, raising an error if such arguments are found.
> 
> 
> 
> Even though my code works, I'm finding it to be a bit clunky.  And now, I'm writing a new class which has subclasses, and so actually keeps the "extra" kwargs instead of raising an error... This is causing me to re-evaluate my original code.
> 
> 
> 
> It also leads me to ask: is there a CLEAN and BROADLY-APPLICABLE way for handling the *args/**kwargs/default values shuffle that I can study?  Or is this sort of thing too idiosyncratic for there to be a general method?
> 
> 
> 
> Thanks for any pointers!

Elegance is a matter of taste, but here is one pattern.


I tend to think that a very long argument lists are either the result of poor design or an indication that readability would benefit from some sort of dedicated, featherweight "parameter" or "builder" object. The builder object is mutable and copied by any functions that consume it. 

To my mind, a nice pattern can be as follows.
--> Class A is a worker class
--> Class B is a worker-builder (or worker-parameter). 
--> You build B first
-->--> usually by first calling a constructor with few to no arguments and then by setting specific properties of B.
--> You pass B to the constructor of A, which copies the data over to control the mutability of A.
--> A has a getter code that returns a copy of it's saved, private B data, so that you can "remember" later on how it was built.

The other point, perhaps more Pythonic, idea here is to exploit this language feature of Python 3 to force argument naming. This would be nice if typical usage involved many possible arguments but only a small number of passed arguments in the typical usage.

http://stackoverflow.com/questions/2965271/forced-naming-of-parameters-in-python



More information about the Python-list mailing list