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). Строковые значения более распространены, чем перечисления. На самом деле я не могу с ходу думать о каких-либо перечислениях (как вы их определяете).