Enum vs String как параметр в функции

Я заметил, что многие библиотеки в настоящее время предпочитают использовать строки через enum-тип переменных параметров.

где люди ранее использовали перечисления, например dateutil.rrule.FR в пятницу кажется, что это сместилось в сторону использования строки (например,'ПТ').

то же самое в numpy (или панд, если на то пошло), где searchsorted например, использование строк (например,side= 'left', или side= 'right'), а не определенное перечисление. Во избежание сомнений, до python 3.4 это могло быть легко реализовано как перечисление как таковое:

class SIDE:
    RIGHT = 0
    LEFT = 1

и преимущества переменной типа перечислений ясны: вы не можете неправильно написать их без возникновения ошибки, они предлагают надлежащую поддержку IDEs и т. д.

Так зачем вообще использовать строки, а не придерживаться типов перечислений? Разве это не делает программы более склонными к ошибкам пользователей? Это не похоже на перечисления создайте накладные расходы-если что-то они должны быть немного более эффективными. Так когда и почему произошел этот сдвиг парадигмы?

4 ответов


ИМХО это дело вкуса. Некоторым нравится такой стиль:

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

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

да, если вы называете searchsorted С side='foo' С AssertionError позже во время выполнения, но по крайней мере ошибка будет довольно легко обнаружить, глядя на отладочных.

в то время как другие люди могут предпочитать (для вас выделил):

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

Я предпочитаю первый, потому что я думаю, что редко используемые константы не стоят пространства имен cruft. Вы можете не соглашаться, и люди могут объединиться. с обеих сторон из-за других проблем.

если вы действительно заботитесь, ничто не мешает вам определить свой собственный "перечисления":

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

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

Я думаю, не стоит, но опять же это дело вкуса.

[обновление]

Стефан сделал справедливое замечание:

как только возникает необходимость изменить значение такого перечисления, поиск и замена строки во многих местах не моя идея веселья :-)

Я вижу, как болезненно это может быть на языке без именованных параметров - используя пример, вы должны искать строку 'right' и получить много ложных срабатываний. В Python вы можете сузить поиск side='right'.

конечно, если вы имеете дело с интерфейсом, который уже имеет определенный набор перечислений/констант (например, внешняя библиотека C), то да, непременно имитируйте существующие соглашения.


Я думаю, что перечисления безопаснее, особенно для больших систем с несколькими разработчиками.

Как только возникает необходимость изменить значение такого перечисления, поиск и замена строки во многих местах не моя идея веселья :-)

наиболее важными критериями IMHO является использование: для использования в модуле или даже пакете строка кажется прекрасной, в общедоступном API я предпочитаю перечисления.


Я предпочитаю строки по причине отладки. сравните объект как

side=1, opt_type=0, order_type=6

to

side='BUY', opt_type='PUT', order_type='FILL_OR_KILL'

мне также нравится "перечисления" , где значения являются строками:

class Side(object):
    BUY = 'BUY'
    SELL = 'SELL'
    SHORT = 'SHORT'

строго говоря, Python не имеет перечислений - или, по крайней мере, до v3.4

https://docs.python.org/3/library/enum.html

Я предпочитаю думать о вашем примере как о постоянных, определенных программистом.

на argparse один набор констант имеют строковые значения. Хотя код использует постоянные имена, пользователи чаще используют строки.

 e.g. argparse.ZERO_OR_MORE = '*'
 arg.parse.OPTIONAL = '?'

numpy является одним из старых пакетов 3rd party (по крайней мере, его корни как numeric are). Строковые значения более распространены, чем перечисления. На самом деле я не могу с ходу думать о каких-либо перечислениях (как вы их определяете).