Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > How to set object parameters nicely?

Reply
Thread Tools

How to set object parameters nicely?

 
 
allen.fowler
Guest
Posts: n/a
 
      12-01-2009
Hello,

I've got a bunch of code that looks something like:

class MyOb(object):
def __init__(self, p1=None, p2=None, p3=None, ...):
self.p1 = p1
self.p2 = p2
self.p3 = p3
self.pN = ...


ob1 = MyOb(p1="Tom", p3="New York")
ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")

.... and so on.

This is fine for only a few parameters, but it's very ugly and a lot
of duplicate typing once I've got 10+ parameters and 5 kinds of
objects.

Is there a better way to do this?

Thanks,

 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      12-01-2009
allen.fowler schrieb:
> Hello,
>
> I've got a bunch of code that looks something like:
>
> class MyOb(object):
> def __init__(self, p1=None, p2=None, p3=None, ...):
> self.p1 = p1
> self.p2 = p2
> self.p3 = p3
> self.pN = ...
>
>
> ob1 = MyOb(p1="Tom", p3="New York")
> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")
>
> ... and so on.
>
> This is fine for only a few parameters, but it's very ugly and a lot
> of duplicate typing once I've got 10+ parameters and 5 kinds of
> objects.
>
> Is there a better way to do this?


There are some tricks. Like this


def __init__(self, p1=None, ...):
d = locals()
del d["self"]
self.__dict__.update(d)


However, it looks like a code-smell for me if you have 10+ paramters.

Diez
 
Reply With Quote
 
 
 
 
MRAB
Guest
Posts: n/a
 
      12-01-2009
allen.fowler wrote:
> Hello,
>
> I've got a bunch of code that looks something like:
>
> class MyOb(object):
> def __init__(self, p1=None, p2=None, p3=None, ...):
> self.p1 = p1
> self.p2 = p2
> self.p3 = p3
> self.pN = ...
>
>
> ob1 = MyOb(p1="Tom", p3="New York")
> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")
>
> ... and so on.
>
> This is fine for only a few parameters, but it's very ugly and a lot
> of duplicate typing once I've got 10+ parameters and 5 kinds of
> objects.
>
> Is there a better way to do this?
>


class MyOb(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

ob1 = MyOb(p1="Tom", p3="New York")
ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")

 
Reply With Quote
 
allen.fowler
Guest
Posts: n/a
 
      12-01-2009

> > Is there a better way to do this?

>
> class MyOb(object):
> * * *def __init__(self, **kwargs):
> * * * * *self.__dict__.update(kwargs)
>
> ob1 = MyOb(p1="Tom", p3="New York")
> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")


I've tried this, but have found two issues:

1) I can't set default values.
2) I can't set required values.

In both of the above cases, if the object is created without the
"exact" dict() I expect, all the assumption my methods make about what
is available in "self" fall apart.

Perhaps, as Diez mentioned, my approach is wrong. What would be the
right thing to do in this situation?

-- AF
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      12-01-2009
allen.fowler schrieb:
>>> Is there a better way to do this?

>> class MyOb(object):
>> def __init__(self, **kwargs):
>> self.__dict__.update(kwargs)
>>
>> ob1 = MyOb(p1="Tom", p3="New York")
>> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")

>
> I've tried this, but have found two issues:
>
> 1) I can't set default values.
> 2) I can't set required values.
>
> In both of the above cases, if the object is created without the
> "exact" dict() I expect, all the assumption my methods make about what
> is available in "self" fall apart.
>
> Perhaps, as Diez mentioned, my approach is wrong. What would be the
> right thing to do in this situation?


There is no general answer to this. It depends on your actual problem.

Diez
 
Reply With Quote
 
allen.fowler
Guest
Posts: n/a
 
      12-02-2009
> >>> Is there a better way to do this?
> >> class MyOb(object):
> >> * * *def __init__(self, **kwargs):
> >> * * * * *self.__dict__.update(kwargs)

>
> >> ob1 = MyOb(p1="Tom", p3="New York")
> >> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")

>
> > I've tried this, but have found two issues:

>
> > 1) I can't set default values.
> > 2) I can't set required values.

>
> > In both of the above cases, if theobjectis created without the
> > "exact" dict() I expect, all the assumption my methods make about what
> > is available in "self" fall apart.

>
> > Perhaps, as Diez mentioned, my approach is wrong. * What would be the
> > right thing to do in this situation?

>
> There is no general answer to this. It depends on your actual problem.
>
> Diez


What are some of the patterns that tend to be used?

-- AF
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      12-02-2009
On Dec 2, 12:13*pm, "allen.fowler" <(E-Mail Removed)> wrote:
> > >>> Is there a better way to do this?
> > >> class MyOb(object):
> > >> * * *def __init__(self, **kwargs):
> > >> * * * * *self.__dict__.update(kwargs)

>
> > >> ob1 = MyOb(p1="Tom", p3="New York")
> > >> ob2 = MyOb(p1="Joe", p2="joe@host", p3="New Jersey")

>
> > > I've tried this, but have found two issues:

>
> > > 1) I can't set default values.
> > > 2) I can't set required values.

>
> > > In both of the above cases, if theobjectis created without the
> > > "exact" dict() I expect, all the assumption my methods make about what
> > > is available in "self" fall apart.

>
> > > Perhaps, as Diez mentioned, my approach is wrong. * What would be the
> > > right thing to do in this situation?

>
> > There is no general answer to this. It depends on your actual problem.

>
> What are some of the patterns that tend to be used?


For the record, I don't really agree that a lot of parameters is code
smell. It's maybe a red flag that you are doing too much in one
function and/or class, but nothing inherently shady.

One thing to ask yourself: are there a lot of combinations of
parameters that don't make sense? For example, do you have a lot of
cases where, say, if one parameter is set to x, then parameters a, b,
c, and d do nothing? That would indicate that you should break your
function/class up into smaller, more targeted parts.

However, if all your parameters are orthogonal, that is, if all or
most combinations make sense, then there's no reason ten or twenty
parameters isn't perfectly reasonable.

Whenever I have ten parameters in an __init__, I ususally just write
out the assignments, although more often than not the object's
attributes don't correspond to the parameters one-to-one, so I'd have
to write them out anyway.


Carl Banks
 
Reply With Quote
 
allen.fowler
Guest
Posts: n/a
 
      12-03-2009
On Dec 2, 6:36*pm, Carl Banks <(E-Mail Removed)> wrote:

> For the record, I don't really agree that a lot of parameters is code
> smell. *It's maybe a red flag that you are doing too much in one
> function and/or class, but nothing inherently shady.
>
> One thing to ask yourself: are there a lot of combinations of
> parameters that don't make sense? *For example, do you have a lot of
> cases where, say, if one parameter is set to x, then parameters a, b,
> c, and d do nothing? *That would indicate that you should break your
> function/class up into smaller, more targeted parts.
>
> However, if all your parameters are orthogonal, that is, if all or
> most combinations make sense, then there's no reason ten or twenty
> parameters isn't perfectly reasonable.
>
> Whenever I have ten parameters in an __init__, I ususally just write
> out the assignments, although more often than not the object's
> attributes don't correspond to the parameters one-to-one, so I'd have
> to write them out anyway.
>


Thank you for the thoughtful insight.

In this case, and I am trying to create a number of ORM-like objects.
(Though, there is no database involved.)

So, instances of these classes are acting as records that are shuttled
around in the system, and the object's properties are acting as
values. The parameters are (mostly) orthogonal, but do need defaults,
and some must be required.


 
Reply With Quote
 
Lie Ryan
Guest
Posts: n/a
 
      12-03-2009
On 12/2/2009 10:26 AM, allen.fowler wrote:
> I've tried this, but have found two issues:
>
> 1) I can't set default values.
> 2) I can't set required values.
>
> In both of the above cases, if the object is created without the
> "exact" dict() I expect, all the assumption my methods make about what
> is available in "self" fall apart.
>


You can inspect the dict, something like:

def __init__(self, **kwargs):
required = ['p1', 'p2', 'p3']
optional = {'p4': 'foo', 'p5': 'bar'}
if any(par not in kwargs for par in required):
raise TypeError('required parameter not set')
for par in optional:
if par not in kwargs:
kwargs[par] = optional[par]
# ... do work ...

Tips: turn this parameter checker into a @decorator

But generally, as Diez pointed out your class may be doing too much. Try
splitting it into smaller classes. Passing too much parameter is an
indication of a God Object (or demi-god)
http://en.wikipedia.org/wiki/God_object "He" just knows too much.



===

Unpythonic warning: Java-style code would use several separate
initializers that would be called in order before the object is in a
ready state (but never in an invalid state [!]). The first initializer
merely set all the attributes into some valid state. This is an
*anti-pattern* in python. Avoid it.

def __init__(self):
self.p1 = ''
self.p2 = 0
self.p3 = []
def init_name(self, name):
self.p1 = name

etc, etc...

===
 
Reply With Quote
 
inhahe
Guest
Posts: n/a
 
      12-03-2009
On Thu, Dec 3, 2009 at 9:16 AM, Lie Ryan <(E-Mail Removed)> wrote:
> On 12/2/2009 10:26 AM, allen.fowler wrote:
>>
>> I've tried this, but have found two issues:
>>
>> 1) I can't set default values.
>> 2) I can't set required values.
>>
>> In both of the above cases, if the object is created without the
>> "exact" dict() I expect, all the assumption my methods make about what
>> is available in "self" fall apart.
>>

>


def __init__(self, required1, required2, default1='d1', default2='d2',
**kwargs):
* *for par in kwargs:
* * *self.setattr(par, kwargs[par])
self.required1 = required1
self.required2 = required2
self.default1 = default1
self.default2 = default2

or

def __init__(self, required1, required2, default1='d1', default2='d2',
**kwargs):
* *for par in kwargs:
* * *self.setattr(par, kwargs[par])
self.required1 = required1
self.required2 = required2
self.default1 = default1
self.default2 = default2
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Command Object, Parameters, Set Cursor Type. etc? +Bob+ ASP General 4 11-29-2006 05:51 PM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
does a "parameters"-parameter overwrite the "parameters"-object? Florian Loitsch Javascript 11 03-15-2005 03:33 PM
Servlet parameters different from the command line parameters? Jonck van der Kogel Java 2 05-26-2004 11:34 PM



Advertisments