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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Phillip B Oldham

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

    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?
  • John Machin

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

    On Jun 14, 12:25 pm, Phillip B Oldham <phillip.old... @gmail.com>
    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

    Comment

    • Bruno Desthuilliers

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

      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

      Comment

      Working...