在python中,如何将传递的变量限制为特定值?

在python中,如何将传递的变量限制为特定值?,python,parameter-passing,argparse,predefined-variables,Python,Parameter Passing,Argparse,Predefined Variables,我正在编写脚本,通过argparse模块使用CLI传递值。我想知道这是否可以限制变量保持预定义的值,以避免用户错误。这不是类型限制,值由字母和数字组成,当然我可以写一个if块,但是我有大约30个预定义的值,所以写 if var is value1 or var is value2 ... or var is value30: pass else: print("oops, your value does not fit") 那会很痛苦。正确的方法是什么?与其逐个检查每个项目是否相等

我正在编写脚本,通过argparse模块使用CLI传递值。我想知道这是否可以限制变量保持预定义的值,以避免用户错误。这不是类型限制,值由字母和数字组成,当然我可以写一个if块,但是我有大约30个预定义的值,所以写

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

那会很痛苦。正确的方法是什么?

与其逐个检查每个项目是否相等,不如检查它是否在一组有效项目中

如果变量在{'foo','bar','etc.}中:

另外,不要使用is检查字符串是否相等。使用==。Python中的字符串可能包含与另一个字符串相同的内容,但可能不是同一个对象。编译器应该实习,即重用文本中的字符串,但这只是一种优化。运行时生成的字符串应生成新对象。不过,有一些方法可以手动对他们进行实习

对于这样一个很长的选项列表,我可能会将它们从一个字符串中拆分出来,以创建集合,如

options = set("""
spam
eggs
sausage
bacon
ham
""".split())
然后可以在选项中使用var

您甚至可以将其他哈希类型合并到集合中

options |= {7, 42, False}
尽管用户输入将以字符串形式开始

另一个要考虑的选项是RE模块。正则表达式可以匹配大量相关字符串,有时非常紧凑。这取决于您希望允许的选项类型。

具有以下选项:

接受:

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')
帮助:

如果我定义了一个metavar,那么帮助将是

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

optional arguments:
  -h, --help     show this help message and exit
  --foo CHOICES
或者,如果选项太长,请定义类型函数:

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

因此,您希望将输入限制为30个预定义值,而不必告诉解释器这些值是什么?您可以共享您的值吗?输入add_参数是一个函数-它应该使用字符串,根据需要进行检查和转换。选项可以是字符串列表。Argparse在测试中执行。一长串的选择并不能很好地显示在帮助中。
usage: ipython3 [-h] [--foo CHOICES]

optional arguments:
  -h, --help     show this help message and exit
  --foo CHOICES
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