我正在编写脚本,通过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")
会很痛苦。这样做的正确方法是什么?
不要单独检查每个项目的相等性,而是检查它是否在一组有效项目中。
if var in {'foo', 'bar', 'etc.'}:
另外,不要使用is
检查字符串相等性。使用==
. Python 中的字符串可能包含与另一个字符串相同的内容,但不是同一个对象。编译器应该从文字中实习(即重用)字符串,但这只是一种优化。运行时生成的字符串应该生成新对象。不过,有一些方法可以手动实习。
对于像这样的很长的选项列表,我可能会将它们从字符串中拆分出来以制作集合,例如
options = set("""
spam
eggs
sausage
bacon
ham
""".split())
然后你可以使用var in options
.
您甚至可以将其他可散列类型合并到集合中。
options |= {7, 42, False}
尽管无论如何用户输入都会以字符串开始。
另一个需要考虑的选项是re
模块。正则表达式可以匹配大量相关字符串,有时非常紧凑。这取决于您要允许的选项类型。
与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}
如果我定义了 a 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