使用argparse的nargs='*'参数时结果不符合预期的问题咨询
使用argparse的nargs='*'参数时结果不符合预期的问题咨询
嗨,我来帮你捋清楚这个问题~ 这绝对不是bug,是你对nargs='*'的工作逻辑有点小误解哦!
先给你拆解下nargs='*'的核心特性:只要用户在命令行里明确写了-l这个选项——不管后面有没有跟参数——argparse都会把args.list解析成一个列表:
- 要是跟了参数,比如
foo -l alpha,就得到包含参数的列表['alpha'] - 要是没跟参数,比如
foo -l,就得到空列表[]
而你设置的default=None,只有在用户完全没写-l选项的时候才会生效哦!
再看你的代码逻辑:你用if (args.list)来判断,在Python里,空列表[]会被视为布尔值False,所以当你运行foo -l时,这个判断不成立,verb自然还是None;而运行foo -l alpha时,非空列表['alpha']被视为True,才会进入分支把verb设为LIST。
下面根据你的实际需求给两个解决方案:
情况1:只要用户写了-l(不管有没有参数),都要触发LIST操作
那你应该判断这个选项是否被用户明确指定了,也就是检查args.list是不是None(因为只有没写-l时才会是None)。修改后的代码如下:
import argparse def parse_cmd_line(): verb = None parser = argparse.ArgumentParser(description='stuff') # 这里的default=None依然保留,用来区分用户是否指定了-l parser.add_argument('-l', '--list', nargs='*', default=None, help='list contents') args = parser.parse_args() # 只要用户指定了-l,不管有没有参数都进入分支 if args.list is not None: verb = 'LIST' print("LIST") print("verb = ", str(verb)) parse_cmd_line()
这样运行foo -l时,args.list是[](不是None),会进入分支,输出LIST和verb = LIST,完全符合你的预期。
情况2:只有当-l后面跟了至少一个参数时,才触发LIST操作
那你的原代码逻辑其实是对的,只是你之前误解了nargs='*'的返回值。这种情况下,空列表不会触发分支,只有带参数时才会触发,如果你需要的就是这个效果,那代码没问题,只是要明白为什么foo -l时verb是None。
总的来说,核心就是搞清楚nargs='*'的返回规则——它会优先用列表覆盖你设置的默认值,只有用户完全不碰这个选项时,默认值才会生效。根据你的实际需求调整判断条件就好啦!




