FAQ
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?

Search Discussions

  • George Sakkis at Oct 3, 2007 at 6:27 pm

    On Oct 3, 1:04 pm, Adam Lanier wrote:
    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
  • George Sakkis at Oct 3, 2007 at 6:47 pm

    On Oct 3, 2:27 pm, George Sakkis wrote:
    On Oct 3, 1:04 pm, Adam Lanier wrote:


    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
  • Adam Lanier at Oct 3, 2007 at 7:38 pm

    On Wed, 2007-10-03 at 18:47 +0000, George Sakkis wrote:

    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...
  • Wildemar Wildenburger at Oct 3, 2007 at 8:21 pm

    Adam Lanier wrote:
    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":
    result = a if condition_is_true else b
    /W

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedOct 3, '07 at 5:04p
activeOct 3, '07 at 8:21p
posts5
users3
websitepython.org

People

Translate

site design / logo © 2022 Grokbase