Question

I am writing a Python function (2.7) where one of the input parameters is a string. The string value should be one of a few values.

i.e. the parameter, in this case "sort" could be any from the list ['first author' 'last author' 'title'] ( the list is actually a bit longer)

Is there a nice way of helping the user supply this input (via tab completion). The ultimate goal is to try and improve the interface for the user so that it is easier for them to use my code and to make less mistakes.

Option 1: Define constants

This might be the best option but there are multiple ways of doing this. My approach is below.

I'm considering creating constants in the module in which the function resides, but this seems messy. My current solution is to include a class with the options, but this makes the input really long, unless I cheat and make the class something nonsensical and short (which is what I've done but it seems wrong and non-obvious). What should I do?

Option 2: Via interpreted documentation

NOTE: I don't think this option actually exists ...

I like the idea of placing code in the documentation which editors could use to perform tab-complete, but I'm not aware of this option existing.

Other options?

Current code (roughly):

class C(): 
    SORT_FIRST_AUTHOR = 'first author'
    SORT_LAST_AUTHOR  = 'last author'
    SORT_TITLE        = 'title'

 #Ideally these might be selected by: my_module.search.sort_option.FIRST_AUTHOR instead of my_module.C.FIRST_AUTHOR but that's REALLY long


def search(query_string,sort = None): #Changed sort = [], to sort = None per comments

UPDATE: (Trying to clarify the question)

This is somewhat similar to this question, although I think the answers diverge from what I'm looking for because of the specifics of the question.

Pythonic way to have a choice of 2-3 options as an argument to a function

Ideally, I would like the definition of search() to allow tab completion on "sort" by having specifications, something like:

def search(....):
   """
   :param sort:
   :values sort: 'first author'|'last author'|'title'
   """

But, I'm not aware of that actually being a valid documentation option.

alternatively, I could define some constants that allows this so that the call becomes:

search(my_a,my_b,package_name.C.SORT_FIRST_AUTHOR)

But this seems ugly and wrong.

So when you want the user to pass in one out of a set of options, how do you do it?

Was it helpful?

Solution

Relying on a user to correctly type a string literal is usually a bad idea as it can result in silent errors if the string contains a typo.

It is common to define uppercase variables at the module level, for instance the socket module has

socket.SOCK_STREAM
socket.SOCK_DGRAM
socket.SOCK_RAW

These are passed to functions as parameters, and could easily contain string values.

"Ideally these might be selected by: my_module.search.sort_option.FIRST_AUTHOR instead of my_module.C.FIRST_AUTHOR but that's REALLY long"

Yes that first option seems a bit long. mymodule.SORT_FIRST_AUTHOR seems reasonable though, and using class variables could be appropriate if the constants are constrained to that class and/or if the class is likely to be imported from the module independently.

from mymodule import Searcher
s = Searcher(..., Searcher.SORT_FIRST_AUTHOR)

Prefixing the constants with a common term (like SORT) will aide editors when tab completing entries and makes the constants more descriptive.

You could also consider using a namedtuple

>>> SortOpts = namedtuple('SortOpts', ('FIRST_AUTHOR', 'LAST_AUTHOR'))
>>> SORT_OPT = SortOpts(FIRST_AUTHOR=0, LAST_AUTHOR=1)
>>> SORT_OPT.FIRST_AUTHOR
0
>>> SORT_OPT.FIRST_AUTHOR = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

This has the advantage of protecting the attributes from being changed, however I don't think this will work with tab completion in most editors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top