Enum vs String as a parameter in a function

I think enums are safer especially for larger systems with multiple developers.

As soon as the need arises to change the value of such an enum, looking up and replacing a string in many places is not my idea of fun :-)

The most important criteria IMHO is the usage: for use in a module or even a package a string seems to be fine, in a public API I'ld prefer enums.


[update]

As of today (2019) Python introduced dataclasses - combined with optional type annotations and static type analyzers like mypy I think this is a solved problem.

As for efficiency, attribute lookup is somewhat expensive in Python compared to most computer languages so I guess some libraries may still chose to avoid it for performance reasons.

[original answer]

IMHO it is a matter of taste. Some people like this style:

def searchsorted(a, v, side='left', sorter=None):
    ...
    assert side in ('left', 'right'), "Invalid side '{}'".format(side)
    ...

numpy.searchsorted(a, v, side='right')

Yes, if you call searchsorted with side='foo' you may get an AssertionError way later at runtime - but at least the bug will be pretty easy to spot looking the traceback.

While other people may prefer (for the advantages you highlighted):

numpy.searchsorted(a, v, side=numpy.CONSTANTS.SIDE.RIGHT)

I favor the first because I think seldom used constants are not worth the namespace cruft. You may disagree, and people may align with either side due to other concerns.

If you really care, nothing prevents you from defining your own "enums":

class SIDE(object):
    RIGHT = 'right'
    LEFT = 'left'

numpy.searchsorted(a, v, side=SIDE.RIGHT)

I think it is not worth but again it is a matter of taste.

[update]

Stefan made a fair point:

As soon as the need arises to change the value of such an enum, looking up and replacing a string in many places is not my idea of fun :-)

I can see how painful this can be in a language without named parameters - using the example you have to search for the string 'right' and get a lot of false positives. In Python you can narrow it down searching for side='right'.

Of course if you are dealing with an interface that already has a defined set of enums/constants (like an external C library) then yes, by all means mimic the existing conventions.