By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,001 Members | 1,176 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,001 IT Pros & Developers. It's quick & easy.

handling many default values

P: n/a
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
Nov 10 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
At Friday 10/11/2006 14:11, Alan G Isaac wrote:
>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.)
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
Nov 10 '06 #2

P: n/a
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:ma***************************************@pyt hon.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
Nov 11 '06 #3

P: n/a
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.

Nov 11 '06 #4

P: n/a

Alan Isaac wrote:
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:ma***************************************@pyt hon.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
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)

Nov 11 '06 #5

P: n/a
"Alan Isaac" <ai****@american.eduwrites:
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

Nov 11 '06 #6

P: n/a
Ben Finney wrote:
"Alan Isaac" <ai****@american.eduwrites:
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

Nov 11 '06 #7

P: n/a
"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
Nov 11 '06 #8

P: n/a
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

Nov 13 '06 #9

P: n/a
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."
--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ˇgratis!
ˇAbrí tu cuenta ya! - http://correo.yahoo.com.ar
Nov 13 '06 #10

P: n/a
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

Nov 14 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.