Как ограничить передаваемую переменную конкретными значениями в Python? - PullRequest
0 голосов
/ 02 декабря 2018

Я пишу скрипт, в котором я передаю значения через CLI через argparse модуль.Мне интересно, если это возможно, чтобы ограничить переменную для хранения предопределенных значений, чтобы избежать ошибки пользователя.Это не ограничение типа, значения состоят из букв и цифр, конечно, я могу записать блок if, но у меня есть около 30 предопределенных значений, поэтому пишу что-то вроде

if var is value1 or var is value2 ... or var is value30:
  pass
else:
    print("oops, your value does not fit")

было бы больно.Как правильно это сделать?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

С choices:

In [214]: parser = argparse.ArgumentParser()
In [215]: parser.add_argument('--foo', choices=['one','two','three','four']);

Принято:

In [216]: parser.parse_args('--foo one'.split())
Out[216]: Namespace(foo='one')

отклонено:

In [217]: parser.parse_args('--foo five'.split())
usage: ipython3 [-h] [--foo {one,two,three,four}]
ipython3: error: argument --foo: invalid choice: 'five' (choose from 'one', 'two', 'three', 'four')

Справка:

In [218]: parser.parse_args('-h'.split())
usage: ipython3 [-h] [--foo {one,two,three,four}]

optional arguments:
  -h, --help            show this help message and exit
  --foo {one,two,three,four}

Если бы я определил metavar, помощь будет

usage: ipython3 [-h] [--foo CHOICES]

optional arguments:
  -h, --help     show this help message and exit
  --foo CHOICES

Или, если выбор слишком длинный, определите функцию type:

In [222]: def mychoices(astr):
     ...:     if astr in ['one','two','three','four']:
     ...:         return astr
     ...:     else:
     ...:         raise argparse.ArgumentTypeError('Wrong choice')

In [223]: parser = argparse.ArgumentParser()
In [224]: parser.add_argument('--foo', type=mychoices);

In [225]: parser.parse_args('--foo one'.split())
Out[225]: Namespace(foo='one')

In [226]: parser.parse_args('--foo five'.split())
usage: ipython3 [-h] [--foo FOO]
ipython3: error: argument --foo: Wrong choice

In [227]: parser.parse_args('-h'.split())
usage: ipython3 [-h] [--foo FOO]

optional arguments:
  -h, --help  show this help message and exit
  --foo FOO
0 голосов
/ 02 декабря 2018

Вместо проверки на равенство для каждого элемента в отдельности, проверьте, входит ли он в набор допустимых элементов.

if var in {'foo', 'bar', 'etc.'}:

Кроме того, не используйте is проверку строкиравенство.Используйте ==.Возможно, что строка в Python может содержать то же содержимое, что и другое, но не быть тем же объектом.Компилятор должен интернировать (то есть повторно использовать) строки из литералов, но это всего лишь оптимизация.Строки, генерируемые во время выполнения, должны создавать новые объекты.Однако есть способы интернировать их вручную.


Для очень длинного списка таких опций я бы, вероятно, отделил их от строки, чтобы создать набор, например

options = set("""
spam
eggs
sausage
bacon
ham
""".split())

Затем вы можете использовать var in options.

Вы можете даже объединить другие типы хэширования в набор.

options |= {7, 42, False}

Хотя пользовательский ввод все равно будет начинаться как строка.


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

...