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
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
"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
> 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.
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)
> 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
> "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
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
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
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
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