Best way to make a number of tests against an object('s attributes)with absence of switch statement?

Discussion in 'Python' started by Phillip B Oldham, Jun 14, 2008.

  1. What would be the optimal/pythonic way to subject an object to a
    number of tests (based on the object's attributes) and redirect
    program flow?

    Say I had the following:

    pets[0] = {'name': 'fluffy', 'species': 'cat', 'size': 'small'}
    pets[1] = {'name': 'bruno', 'species': 'snake', 'size': 'small'}
    pets[2] = {'name': 'rex', 'species': 'dog', 'size': 'large'}

    What I'd like to do is loop through 'pets', and test each object. Some
    of the tests I'd like to perform are:

    Is the size 'small' and species not 'dog'?
    Is the species 'cat' and name 'fluffy'?
    Is the species not 'dog' or 'cat'?

    In PHP I'd use a switch statement similar to the following:

    foreach( $pets as $pet) {
    switch(true) {
    case ( $pet['size'] === 'small' && $pet['species'] !== 'dog' ):
    // do something
    break;
    // etc...
    }
    }

    Now, I understand from a bit of googling that python doesn't have a
    switch statement, and because of this people rely on python's
    polymorphism. Thats great, but I've yet to come across a decent
    example which make a "click".

    Any thoughts on how to proceed?
    Phillip B Oldham, Jun 14, 2008
    #1
    1. Advertising

  2. Phillip B Oldham

    John Machin Guest

    Re: Best way to make a number of tests against an object('sattributes) with absence of switch statement?

    On Jun 14, 12:25 pm, Phillip B Oldham <>
    wrote:
    > What would be the optimal/pythonic way to subject an object to a
    > number of tests (based on the object's attributes) and redirect
    > program flow?
    >
    > Say I had the following:
    >
    > pets[0] = {'name': 'fluffy', 'species': 'cat', 'size': 'small'}
    > pets[1] = {'name': 'bruno', 'species': 'snake', 'size': 'small'}
    > pets[2] = {'name': 'rex', 'species': 'dog', 'size': 'large'}


    I'd suggest that you have a Pet class, instead of using dicts.

    > What I'd like to do is loop through 'pets', and test each object. Some
    > of the tests I'd like to perform are:
    >
    > Is the size 'small' and species not 'dog'?
    > Is the species 'cat' and name 'fluffy'?
    > Is the species not 'dog' or 'cat'?
    >
    > In PHP I'd use a switch statement similar to the following:
    >
    > foreach( $pets as $pet) {
    > switch(true) {
    > case ( $pet['size'] === 'small' && $pet['species'] !== 'dog' ):
    > // do something
    > break;
    > // etc...
    >
    > }
    > }
    >
    > Now, I understand from a bit of googling that python doesn't have a
    > switch statement, and because of this people rely on python's
    > polymorphism. Thats great, but I've yet to come across a decent
    > example which make a "click".
    >
    > Any thoughts on how to proceed?


    A switch statement is "optimal" when a variable needs to be tested
    against N known constant values ... a compiler can emit code that
    takes O(1) time (or O(log(N)) if the constants are sparse) instead of
    O(N).

    However the way you are using switch, it can't be other than O(N) and
    it is just syntactic lemon juice for not having (or not using) if ...
    elif ... else.

    Python version:

    for pet in pets:
    if pet.size == 'small' and pet.species != 'dog':
    pet.feed() # class instances can have user-definable methods
    # don't need "break" to escape from if statement
    elif ..... etc ...

    HTH,
    John
    John Machin, Jun 14, 2008
    #2
    1. Advertising

  3. Phillip B Oldham a écrit :
    > What would be the optimal/pythonic way to subject an object to a
    > number of tests (based on the object's attributes) and redirect
    > program flow?
    >
    > Say I had the following:
    >
    > pets[0] = {'name': 'fluffy', 'species': 'cat', 'size': 'small'}
    > pets[1] = {'name': 'bruno', 'species': 'snake', 'size': 'small'}
    > pets[2] = {'name': 'rex', 'species': 'dog', 'size': 'large'}
    >
    > What I'd like to do is loop through 'pets', and test each object. Some
    > of the tests I'd like to perform are:
    >
    > Is the size 'small' and species not 'dog'?
    > Is the species 'cat' and name 'fluffy'?
    > Is the species not 'dog' or 'cat'?
    >
    > In PHP I'd use a switch statement similar to the following:
    >
    > foreach( $pets as $pet) {
    > switch(true) {
    > case ( $pet['size'] === 'small' && $pet['species'] !== 'dog' ):
    > // do something
    > break;
    > // etc...
    > }
    > }
    >
    > Now, I understand from a bit of googling that python doesn't have a
    > switch statement, and because of this people rely on python's
    > polymorphism.


    You could also put it the other way round : Python doesn't have a switch
    statement because peoples use polymorphism !-)

    (nb : not that my "reversed" statement is in any way more true than
    yours - but the fact is that procedural switch statement vs OO
    polymorphic dispatch is not such a new topic...)

    > Thats great, but I've yet to come across a decent
    > example which make a "click".
    >
    > Any thoughts on how to proceed?


    The braindead canonical OO solution would be to make a specific class
    for each species each implementing it's own version of do_something().
    The problem is that it would only dispatch on species, not other
    attributes (size etc). Which is a inherent limitation of the canonical
    OO type-based single dispatch mechanism.

    A more elaborate canonical OO solution would be to use the visitor
    pattern to overcome the single dispatch limitation.

    A yet more elaborate (but way less canonical) solution is to use
    predicate-based dispatch (cf Philip Eby's work).

    Anyway, and while each dispatch mechanism (from basic branching to
    complex predicate-based systems) has it's pros and cons, I'd first think
    twice (or more) about whether my current dispatch problem has some
    relative stability wrt/ the domain - IOW, it's structurally part of the
    domain and won't change anytime soon - or if it's one of those ad-hoc
    short-lived illogical "business rule" that is potentially subject to
    unpredictable change any other day. Because the appropriate solution
    really depends on this kind of considerations.

    Now wrt/ your concrete example: truth is that, while expressed as a
    switch statement, it's in fact really a if/elif/.../, since the
    condition is not a constant (so you don't gain any performance gain from
    using a switch). So the simplest translation in Python is to use an
    if/elif/...


    for pet in pets:
    if pet['size'] == 'small' and pet['species'] !== 'dog':
    // do something
    elif (other complex condition):
    // etc
    Bruno Desthuilliers, Jun 16, 2008
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    8
    Views:
    879
  2. Replies:
    21
    Views:
    1,031
    Giannis Papadopoulos
    Aug 2, 2005
  3. bthumber
    Replies:
    5
    Views:
    407
    Alexey Smirnov
    Jan 29, 2009
  4. dayo
    Replies:
    11
    Views:
    326
    Ilya Zakharevich
    Dec 16, 2005
  5. Roy Smith
    Replies:
    2
    Views:
    165
    Steven D'Aprano
    Mar 4, 2013
Loading...

Share This Page