Class design question

A

Adam Lanier

Relatively new to python development and I have a general question
regarding good class design.

Say I have a couple of classes:

Class Foo:
params = [ ]
__init__( self, param ):
...

Class Bar:
data = None
__init__( self, data ):
...

The class is going to be a wrapper around a list of Bars() (among other
things). I want the ability to pass to the constructor of Foo either:
a string 'baz'
a Bar object Bar( 'baz' )
a list of strings and/or bars ( 'baz', Bar( 'something else' ))


Am I going to have to use isinstance() to test the parameter to __init__
to see what type of data I'm passing in, i.e.,

Class Foo:
params = [ ]
__init__( self, param ):
if isinstance( param, list ):
for p in param:
addParam( p )
elif isinstance( param, str):
addParam( param )

addParam( self, param ):
if isinstance( param, Bar ):
self.params.add( param )
elif isinstance( param, str ):
self.params.add( Bar( param ))
else:
raise TypeError( "wrong type of input" )

Am I missing something here or is there a more Pythonic way to
accomplish this?
 
G

George Sakkis

Relatively new to python development and I have a general question
regarding good class design.

Say I have a couple of classes:

Class Foo:
params = [ ]
__init__( self, param ):
...

Class Bar:
data = None
__init__( self, data ):
...

The class is going to be a wrapper around a list of Bars() (among other
things). I want the ability to pass to the constructor of Foo either:
a string 'baz'
a Bar object Bar( 'baz' )
a list of strings and/or bars ( 'baz', Bar( 'something else' ))

Am I going to have to use isinstance() to test the parameter to __init__
to see what type of data I'm passing in, i.e.,

Class Foo:
params = [ ]
__init__( self, param ):
if isinstance( param, list ):
for p in param:
addParam( p )
elif isinstance( param, str):
addParam( param )

addParam( self, param ):
if isinstance( param, Bar ):
self.params.add( param )
elif isinstance( param, str ):
self.params.add( Bar( param ))
else:
raise TypeError( "wrong type of input" )

Am I missing something here or is there a more Pythonic way to
accomplish this?

I would use variable argument list for this; it's also consistent with
your example Foo( 'baz', Bar( 'something else' )), otherwise you need
to call it as Foo([ 'baz', Bar( 'something else' ) ])

# always inherit from object unless you have a good reason not to
class Foo(object):

# XXX this is a class instance, shared by all Foo instances;
# XXX probably not what you intended
params = [ ]

def __init__(self, *args):
# uncomment the following line for instance-specific params
# self.params = []
for arg in args:
if not isinstance(arg, Bar):
# let the Bar constructor to do typechecking or whatnot
arg = Bar(arg)
self.params.add(arg)


HTH,
George
 
G

George Sakkis

Relatively new to python development and I have a general question
regarding good class design.
Say I have a couple of classes:
Class Foo:
params = [ ]
__init__( self, param ):
...
Class Bar:
data = None
__init__( self, data ):
...
The class is going to be a wrapper around a list of Bars() (among other
things). I want the ability to pass to the constructor of Foo either:
a string 'baz'
a Bar object Bar( 'baz' )
a list of strings and/or bars ( 'baz', Bar( 'something else' ))
Am I going to have to use isinstance() to test the parameter to __init__
to see what type of data I'm passing in, i.e.,
Class Foo:
params = [ ]
__init__( self, param ):
if isinstance( param, list ):
for p in param:
addParam( p )
elif isinstance( param, str):
addParam( param )
addParam( self, param ):
if isinstance( param, Bar ):
self.params.add( param )
elif isinstance( param, str ):
self.params.add( Bar( param ))
else:
raise TypeError( "wrong type of input" )
Am I missing something here or is there a more Pythonic way to
accomplish this?

I would use variable argument list for this; it's also consistent with
your example Foo( 'baz', Bar( 'something else' )), otherwise you need
to call it as Foo([ 'baz', Bar( 'something else' ) ])

# always inherit from object unless you have a good reason not to
class Foo(object):

# XXX this is a class instance, shared by all Foo instances;
# XXX probably not what you intended
params = [ ]

def __init__(self, *args):
# uncomment the following line for instance-specific params
# self.params = []
for arg in args:
if not isinstance(arg, Bar):
# let the Bar constructor to do typechecking or whatnot
arg = Bar(arg)
self.params.add(arg)

HTH,
George

Or even better (Python 2.5):

class Foo(object):
def __init__(self, *args):
self.params = [arg if isinstance(arg, Bar) else Bar(arg) for
arg in args]

George
 
A

Adam Lanier

I would use variable argument list for this; it's also consistent with
your example Foo( 'baz', Bar( 'something else' )), otherwise you need
to call it as Foo([ 'baz', Bar( 'something else' ) ])

Good point, this is what was tripping me up...
# always inherit from object unless you have a good reason not to
class Foo(object):

# XXX this is a class instance, shared by all Foo instances;
# XXX probably not what you intended
params = [ ]

def __init__(self, *args):
# uncomment the following line for instance-specific params
# self.params = []
for arg in args:
if not isinstance(arg, Bar):
# let the Bar constructor to do typechecking or
whatnot

This is also tangentially what I was asking, Should type-checking be
done in the caller or the callee (so to speak). I guess good OOP
practice would be to push it down the call stack.
arg = Bar(arg)
self.params.add(arg)

Or even better (Python 2.5):

class Foo(object):
def __init__(self, *args):
self.params = [arg if isinstance(arg, Bar) else Bar(arg) for
arg in args]

Interesting, I'm not familiar with this idiom...
 
W

Wildemar Wildenburger

Adam said:
class Foo(object):
def __init__(self, *args):
self.params = [arg if isinstance(arg, Bar) else Bar(arg) for
arg in args]

Interesting, I'm not familiar with this idiom...
These are two idioms actually:

1. a "list comprehension":
>>> newlist = [return_something(item) for item in some_iterable]

2. where return_something(item) is a "conditional assignment":
/W
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top