2

My Python project has the ability to perform operations on two different destinations, let's call them SF and LA. Which is the better way to accomplish this?

Option A:

destinations.py

LA = 1
SF = 2

example_operation.py

import destinations
run_operation(destination=destinations.LA)

def run_operation(destination):
    assert destination in [destinations.LA, destinations.SF]
    ...

OR

Option B:

example_operation.py

run_operation(destination='LA')

def run_operation(destination):
    assert destination in ['LA', 'SF']
    ...

I realize I can also use a dictionary or many other methods to accomplish this. I'd like to know which is the best practice for declaring and validating these.

disambiguator
  • 169
  • 1
  • 12
  • For membership testing a set is more efficient - `DESTINATIONS = set(('LA', 'SF'))` then `assert destination in DESTINATIONS`. But where else will you need these values? – jonrsharpe Jan 20 '15 at 21:03
  • This is very subjective and won’t really yield any good answers. You could combine both though and do `LA = 'LA'` and `SF = 'SF'`. – poke Jan 20 '15 at 21:14
  • @jonrsharpe I'm not too concerned about performance, but thank you. The "destination" is used to determine a load address later. – disambiguator Jan 20 '15 at 21:30
  • @disambiguator If you are loading an address from somewhere (e.g. from a dictionary), then it’s fine if the code throws a key error at that point when an invalid argument was passed. – poke Jan 20 '15 at 21:34

1 Answers1

0

Since it’s very subjective, I’ll avoid commenting on which way would be better. You could try to argue from a performance point (integers are faster than strings, but variable lookups are slower than constants?), or from a code completion view (editors could auto-complete the variables), or extensibility (you can easily use a new string for something new), but in the end, it doesn’t really matter much: It’s mostly personal preference.

What I want to try to comment on however is the validation question: How to validate such arguments? My usual answer to that is: Don’t.

Python is usually used without many fail-safes. For example, Python doesn’t have true private members, and large parts of the stdlib even go without hiding their internals completely. If you want, you can use those internals, mess with all the things—but if something breaks, it’s your problem. So often, you would just expect users to use your code correctly: If they pass in a parameter your function doesn’t expect, then, well, something will fail. Of course it is not bad to have some kind of validation but you usually don’t need to put asserts everywhere.

poke
  • 307,619
  • 61
  • 472
  • 533
  • Appreciate your answer. I'll try to find a good spot for validation and only do it once. – disambiguator Jan 20 '15 at 21:33
  • Just to add to the answer, there does not seem to be one preferred way to do this throughout the standard library (e.g. `'w'` parameter to `open()` vs `subprocess.PIPE` and etc). – Rafael Lerm Jan 20 '15 at 21:43
  • Also, a very good answer (explaining new features in py3.4), can be found [here](http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python?rq=1) – Rafael Lerm Jan 20 '15 at 21:44
  • thanks @RafaelLerm, my question is more if I even need the enum, which it seems I don't. I just need to make sure there's some sort of validation. – disambiguator Jan 20 '15 at 22:27