Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

handling many default values

0 views
Skip to first unread message

Alan G Isaac

unread,
Nov 10, 2006, 12:11:24 PM11/10/06
to
My class MyClass reuses many default parameters
with a small number of changes in each instance.
For various reasons I decided to put all the
parameters in a separate Params class, instances
of which reset the default values based on keyword
arguments, like this:

class Params:
def __init__(self,**kwargs):
#set lots of default values
...
#set the deviations from defaults
self.__dict__.update(kwargs)

Is this a reasonable approach overall?
(Including the last line.)

Thanks,
Alan Isaac

Gabriel Genellina

unread,
Nov 10, 2006, 6:36:27 PM11/10/06
to Alan G Isaac, pytho...@python.org

I'm not sure what you want to do exactly, but a class attribute acts
as a default instance attribute.

class A(object):
x = 0
y = 20
def __init__(self, x=None, y=None):
if x is not None: self.x = x
if y is not None: self.y = y

class B(A):
z = 3
def __init__(self, x=None, y=None, z=None):
A.__init__(self, x, y)
if z is not None: self.z = z

a = A(1)
print "a.x=",a.x
print "a.y=",a.y

b = B(z=8)
print "b.x=",b.x
print "b.y=",b.y
print "b.z=",b.z

output:

a.x= 1
a.y= 20
b.x= 0
b.y= 20
b.z= 8


--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam Ągratis!
ĄAbrí tu cuenta ya! - http://correo.yahoo.com.ar

Alan Isaac

unread,
Nov 11, 2006, 8:10:54 AM11/11/06
to
> At Friday 10/11/2006 14:11, Alan G Isaac wrote:
> >class Params:
> > def __init__(self,**kwargs):
> > #set lots of default values
> > ...
> > #set the deviations from defaults
> > self.__dict__.update(kwargs)
> >
> >Is this a reasonable approach overall?
> >(Including the last line.)


"Gabriel Genellina" wrote in message
news:mailman.2074.1163201...@python.org...


> I'm not sure what you want to do exactly, but a class attribute acts
> as a default instance attribute.

Yes. I am sorry my question was not clearer.
There are *many* parameters,
and the list can change,
so I want to avoid listing them all in the Param class's __init__ function,
using the strategy above.

Q1: Is this approach reasonable?
(This is a newbie question about unforseen hazards.)
Q2: Is it horrible design to isolate the parameters in a separate class?
(Comment: currently several classes may rely on (parts of) the same
parameter set.)

Thanks,
Alan Isaac


Steven D'Aprano

unread,
Nov 11, 2006, 9:04:33 AM11/11/06
to
On Fri, 10 Nov 2006 17:11:24 +0000, Alan G Isaac wrote:

> My class MyClass reuses many default parameters
> with a small number of changes in each instance.

Let me see that I understand. Are you doing something like this?

# Class takes a lot of arguments
a = MyClass(0, 1, 2, 3, 4, 5, ..., 99)
# and instances vary only by one or two of those args
b = MyClass(0, 2, 2, 3, 4, 5, ..., 99)
c = MyClass(0, 3, 2, 3, 4, 5, ..., 99)
d = MyClass(0, 4, 2, 3, 4, 5, ..., 99)
e = MyClass(0, 5, 2, 3, 4, 5, ..., 99)
...
z = MyClass(0, 26, 2, 3, 4, 5, ..., 99)

If that's the case, I'd seriously rethink your class design. It is hard to
advise a better design without knowing more about the class, but I'd be
surprised if you can't use subclassing to reduce the number of parameters
needed. E.g.:

class MyClass(object):
def __init__(self, arg0):
self.arg0 = arg0
# now fill in arguments 1 through 99 with sensible values

class MyClass2(MyClass):
def __init__(self, arg1):
"""Just like MyClass, but arg0 has a fixed value and arg1 varies"""
super(MyClass, self).__init__("fixed value")
self.arg1 = arg1

and so on for as many subclasses that you need.

In the same way, perhaps you can group those arguments. E.g. instead of
this:


class WordProcessingDoc(object):
def __init__(self, page_width, page_height, left_margin,
right_margin, top_margin, bottom_margin, font_face,
font_size, font_style, line_size, justification): # and many more
# and many, many more arguments
pass


Create some classes, and pass instances of them to the main class:

class CharStyle(object):
def __init__(self, font_face, font_size, font_style):
pass
class PageStyle(object):
def __init__(self, width, height, left, right, top, bottom):
pass

class WordProcessingDoc(object):
def __init__(self, pagestyle, charstyle, paragraphstyle):
pass

> For various reasons I decided to put all the
> parameters in a separate Params class, instances
> of which reset the default values based on keyword
> arguments, like this:
>
> class Params:
> def __init__(self,**kwargs):
> #set lots of default values
> ...
> #set the deviations from defaults
> self.__dict__.update(kwargs)
>
> Is this a reasonable approach overall?
> (Including the last line.)

(1) If there really is no alternative to a class with many arguments;
(2) and instances can vary those arguments unpredictably;

then this approach seems reasonable to me. But I really suggest you
rethink your class design.

--
Steven.

pgar...@acay.com.au

unread,
Nov 11, 2006, 9:07:13 AM11/11/06
to
Hi,
I kind of had a similar problem when I was developing a 3d OO engine.
I had many
bigger things composed of lots of little things, and a lot of code was
spent
initializing the little things in constructors.

So I just passed a reference of the bigger thing to the little thing in
its constructor, thus saving a lot
of parameter passing and variable setup and copying. In the following
example, big is passed to
little's constructor, instead of all of big's variables.

ie.
class big:
def __init__(self):
self.v1 = ...
self.v2 = ...
self.objects = []
def assemble(self):
self.objects.append(little(self, 1))
self.objects.append(little(self,2))

class little:
def __init__(self, big, n):
self.big = big # Now little has access to v1, v2 by self.big.v1
etc
self.n = n # This makes it different
def a_function(self):
do_something(self.big.v1, self.big.v2)

Ben Finney

unread,
Nov 11, 2006, 2:22:02 PM11/11/06
to pytho...@python.org
"Alan Isaac" <ais...@american.edu> writes:

> There are *many* parameters, and the list can change, so I want to
> avoid listing them all in the Param class's __init__ function, using
> the strategy above.
>
> Q1: Is this approach reasonable?
> (This is a newbie question about unforseen hazards.)
> Q2: Is it horrible design to isolate the parameters in a separate class?
> (Comment: currently several classes may rely on (parts of) the same
> parameter set.)

It's a bad design smell to have functions that accept large numbers of
parameters, many of them optional. Such an interface is difficult to
document, maintain and test.

You should certainly be examining such code and seeing how much of it
can be implemented instead as functions with small, well-defined
parameter lists. This may mean writing more functions, or more layers
of functions, or more classes, or whatever; but having a result that
uses small, well-defined interfaces is a valuable property.

--
\ "The number of UNIX installations has grown to 10, with more |
`\ expected." -- Unix Programmer's Manual, 2nd Ed., 12-Jun-1972 |
_o__) |
Ben Finney

George Sakkis

unread,
Nov 11, 2006, 3:04:21 PM11/11/06
to
Ben Finney wrote:

> "Alan Isaac" <ais...@american.edu> writes:
>
> > There are *many* parameters, and the list can change, so I want to
> > avoid listing them all in the Param class's __init__ function, using
> > the strategy above.
> >
> > Q1: Is this approach reasonable?
> > (This is a newbie question about unforseen hazards.)
> > Q2: Is it horrible design to isolate the parameters in a separate class?
> > (Comment: currently several classes may rely on (parts of) the same
> > parameter set.)
>
> It's a bad design smell to have functions that accept large numbers of
> parameters, many of them optional. Such an interface is difficult to
> document, maintain and test.
>
> You should certainly be examining such code and seeing how much of it
> can be implemented instead as functions with small, well-defined
> parameter lists. This may mean writing more functions, or more layers
> of functions, or more classes, or whatever; but having a result that
> uses small, well-defined interfaces is a valuable property.

So I guess you prefer the (os.system, os.spawn*, os.popen*, popen2.*,
commands.*) kitchen sink than the single versatile subprocess.Popen
class, right ? I respectfully disagree, and I'm all for
one-class-does-it-all, as long as most parameters are optional and the
default values address the most typical/reasonable case.

To answer to OP's question, your approach is totally reasonable and
well-known; the csv.Dialect class for example is exactly this, a
parameter-holding class.

George

Alan Isaac

unread,
Nov 11, 2006, 4:11:38 PM11/11/06
to
"Steven D'Aprano" wrote

> (1) If there really is no alternative to a class with many arguments;
> (2) and instances can vary those arguments unpredictably;
> then this approach seems reasonable to me. But I really suggest you
> rethink your class design.

Thanks to all who replied and to George for his specific example.
Steve's comments seem to summarize the overall sentiment:
there is no *general* objection, but I should make sure my
specific implementation really profits from a parameter holding class
(rather than, e.g., a super class in which appropriate defaults are set).
I believe this is the case, since the many parameters can vary
arbitrarily and do not fall into neat groupings.

Also, as an aside, no one objected to using
self.__dict__.update(kwargs)
in the __init__ function of the parameter holding class.

Thanks,
Alan


Michele Simionato

unread,
Nov 13, 2006, 11:33:31 AM11/13/06
to
Alan Isaac wrote:
> Also, as an aside, no one objected to using
> self.__dict__.update(kwargs)
> in the __init__ function of the parameter holding class.

It is a common trick, also shown in the Python cookbook, IIRC. If you
are anal about
double underscores, you can also use

vars(self).update(kwargs)

Michele Simionato

Gabriel Genellina

unread,
Nov 13, 2006, 2:25:51 PM11/13/06
to Michele Simionato, pytho...@python.org

Not good - that relies on vars() returning the actual __dict__.
From <http://docs.python.org/lib/built-in-funcs.html>:
"The returned dictionary should not be modified: the effects on the
corresponding symbol table are undefined."


--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar

Michele Simionato

unread,
Nov 14, 2006, 3:26:16 AM11/14/06
to
Gabriel Genellina wrote:
> At Monday 13/11/2006 13:33, Michele Simionato wrote:
>
> >Alan Isaac wrote:
> > > Also, as an aside, no one objected to using
> > > self.__dict__.update(kwargs)
> > > in the __init__ function of the parameter holding class.
> >
> >It is a common trick, also shown in the Python cookbook, IIRC. If you
> >are anal about
> >double underscores, you can also use
> >
> >vars(self).update(kwargs)
>
> Not good - that relies on vars() returning the actual __dict__.
> From <http://docs.python.org/lib/built-in-funcs.html>:
> "The returned dictionary should not be modified: the effects on the
> corresponding symbol table are undefined."

I believe the issue is with classes, where vars(klass) returns a
dictproxy which is read only.
In the case of instances (i.e. the OP' case) vars(self) returns the
instance dictionary and
my suggestion is correct. However you was right to point out this
subtility, it is always
worth to know.

Michele Simionato

0 new messages