【问题标题】:Python argparse: Force a list item to be uniquePython argparse:强制列表项是唯一的
【发布时间】:2012-02-21 11:22:14
【问题描述】:

能够使用下面的choices=servers 验证列表项很好。

servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer", "SkeppServer", "HavsServer", "SovServer" ]
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--only', nargs='*', choices=servers, help='Space separated list of case sensitive server names to process')

是否可以强制列表中的项目唯一,从而不允许重复?

【问题讨论】:

  • 只需将服务器列表转换为 set 即可删除重复项。

标签: python argparse


【解决方案1】:

使用argparse 正确丢弃重复项的方法是创建自己的argparse.Action 类,按照其他答案的建议使用set

import argparse

class UniqueAppendAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        unique_values = set(values)
        setattr(namespace, self.dest, unique_values)

servers = ["ApaServer", "BananServer", "GulServer", "SolServer",
           "RymdServer", "SkeppServer", "HavsServer", "SovServer" ]
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--only', nargs='*', choices=servers, action=UniqueAppendAction,
                    help='Space separated list of case sensitive server names to process')
print parser.parse_args()

示例输出:

$ python test.py -o ApaServer ApaServer
Namespace(only=set(['ApaServer']))

【讨论】:

  • args = parser.parse_args() 之后,我看不到简单的args.only = set(args.only) 的任何价值。比编写自定义操作要短得多...
  • @lunaryorn 对于一个单一的论点,我同意这不会很方便。但是,当多个参数应该具有此属性时,在 add_argument 方法调用中设置它会更加一致和可读,因为有关参数的所有信息都在一个地方。
  • 在这种情况下,您仍然可以使用for arg in ('only1', 'only2'): setattr(args, arg, set(getattr(args, arg)))。但我明白你的意思......
【解决方案2】:

我不认为您可以使用argparse 强制执行此操作,但我也看不出有任何理由这样做。只需在help 中记录重复项将被忽略。如果用户将重复的参数传递给--only,让她这样做,并在处理选项参数时忽略重复的参数(例如,在处理之前将列表转换为set())。

【讨论】:

  • 考虑同时向stderr 发出警告,如果发现重复参数将被忽略。
【解决方案3】:

修改米歇尔的回答:

In [1]: x = [5,6,5]

In [2]: x_nodups = list(set(x))

In [3]: x_nodups
Out[3]: [5, 6]

In [4]: x_nodups_michel = dict(map(lambda i: (i,1),x)).keys()

In [5]: x_nodups_michel
Out[5]: [5, 6]

短得多。

【讨论】:

    【解决方案4】:

    这是我用于类似目的的一些代码的摘录:

    def parse_args(argv):
        class SetAction(argparse.Action):
            """argparse.Action subclass to store distinct values"""
            def __call__(self, parser, namespace, values, option_string=None):
                try:
                    getattr(namespace,self.dest).update( values )
                except AttributeError:
                    setattr(namespace,self.dest,set(values))
        ap = argparse.ArgumentParser(
            description = __doc__,
            formatter_class = argparse.ArgumentDefaultsHelpFormatter,
            )
        ap.add_argument('--genes', '-g',
                        type = lambda v: v.split(','),
                        action = SetAction,
                        help = 'select by specified gene')
    

    这在精神上与 jcollado 的回复相似,但略有改进:可以指定多个选项,使用逗号分隔值,并且在所有选项中对它们进行重复数据删除(通过集合)。

    例如:

    snafu$ ./bin/ucsc-bed -g BRCA1,BRCA2,DMD,TNFA,BRCA2 -g BRCA1
    Namespace(genes=set([u'BRCA1', u'BRCA2', u'DMD', u'TNFA']))
    

    请注意,有两个 -g 参数。 BRCA2 在第一次中被指定了两次,但只出现一次。 BRCA1 在第一个和第二个 -g 选项中指定,但也只出现一次。

    【讨论】:

      猜你喜欢
      • 2021-05-12
      • 2018-12-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 2011-06-19
      • 2012-08-28
      • 1970-01-01
      相关资源
      最近更新 更多