More efficient/elegant branching

Tim Chase python.list at tim.thechases.com
Mon Dec 9 08:33:40 EST 2019


On 2019-12-09 12:27, Musbur wrote:
> def branch1(a, b, z):
>      """Inelegant, unwieldy, and pylint complains
>      about too many branches"""
>      if a > 4 and b == 0:
>          result = "first"
>      elif len(z) < 2:
>          result = "second"
>      elif b + a == 10:
>          result = "third"
>      return result

Because of the diversity of test-types, I tend to agree with ChrisA
and be strongly tempted to ignore linting warning.  I have some ETL
code that has umpty-gazillion odd if-conditions like this and they
all update some global-to-the-if/local-to-the-loop state, and if I
split each out somehow, I'd either be passing an object around that I
mutate, or I would do a lot of copy-the-data-updating-one-field per
function.

Alternatively, ...

> def branch2(a, b, z):
>      """Elegant but inefficient because all expressions
>      are pre-computed althogh the first one is most likely
>      to hit"""
> def branch3(a, b, z):
>      """Elegant but inefficient because expressions
>      need to be parsed each time"""

If you really want to do lazy evaluation, you can create a
function for each, which might (or might not) make it easier to read:

  def something_descriptive(a, b, z):
    return a > 4 and b == 0

  def z_is_short(a, b, z):
    return len(z) < 2

  def proper_total(a, b, z)
     return b + a == 10

  def branch4(a, b, z):
    for test, result in [
        (something_descriptive, "first"),
        (z_is_short, "second"),
        (proper_total, "third"),
        ]:
      if test(a, b, z):
        return result
    return "some default"

or possibly

  def something_descriptive(a, b):
    return a > 4 and b == 0

  def z_is_short(z):
    return len(z) < 2

  def proper_total(a, b)
     return b + a == 10

  def branch5(a, b, z):
    for test, params, result in [
        (something_descriptive, (a, b), "first"),
        (z_is_short, (z,), "second"),
        (proper_total, (a, b), "third"),
        ]:
      if test(*params):
        return result
    return "some default"

I'm not sure either of those is necessarily *better*, but they're at
least options that you can try and see if it improves readability in
your particular case.

-tkc






More information about the Python-list mailing list