为什么可以将函数分配给type,const和default?

时间:2015-05-14 19:56:04

标签: python python-3.x argparse

我想了解此代码的工作原理。为什么可以为typeconstdefault提供内置函数?

def printList(i):
    print("Integer:", i)
    return(i)

def getParser():
    from argparse import ArgumentParser

    parser = ArgumentParser()
    parser.add_argument("integers", type=printList, nargs="+")
    parser.add_argument("--sum", dest="accumulate", const=sum, default=max, nargs="?")
    return(parser)


args = getParser().parse_args(["2", "3", "9", "5"])
print(args.integers)
print(args.accumulate(args.integers))

输出:

>>> Integer: 2
>>> Integer: 3
>>> Integer: 9
>>> Integer: 5
>>> ['2', '3', '9', '5'] 
>>> 9

我想了解它的工作原理。

修改

你错误地理解了我。

例如" type"我希望看到" type = int",因为你只想允许整数。所以你给"输入"一些东西。 但在我的例子中"键入"给" printList"功能,以便它可以打印它。 或者例如"默认"。我希望能给出一些价值,比如int或str。我给了"默认"。但在我的例子中,我给出了内置函数" max"。为什么" max"得到一个清单? 为什么这样?这就是我想知道的。

3 个答案:

答案 0 :(得分:1)

parser.add_argument("--sum", dest="accumulate", const=sum, default=max, nargs="?")

是,假设您没有提供'--sum'的参数, little 位如下:

args.accumulate = sum if '--sum' in arg_list else max
                               # ^ it also needs to be in the right place!

the docs for nargs='?'

  

如果可能,将从命令行使用一个参数,并且   作为单个项目生产。如果没有命令行参数,则   将生成默认值。请注意,对于可选参数,   还有一个案例 - 选项字符串存在但不存在   然后是命令行参数。在这种情况下,const的值   将被制作。

函数是Python中的第一类对象,可以像任何其他对象一样传递,因此没有理由不能将它们用于constdefault

请注意,如果您实际上 提供了'--sum'的参数,那么args.accumulate就是该值:

>>> args = getParser().parse_args(["1", "--sum", "this one"])
('Integer:', '1')
>>> args.accumulate
'this one'

答案 1 :(得分:0)

简短回答:

argparse期望type是可调用的(对字符串的限制有限)。

argparse允许constdefault几乎任何内容。它不会对它们执行任何操作,除非将它们分配给属性(或将它们传递给type可调用的)。

答案很长:

从内部文档中,class Action

  
      
  • type - 一个可接受单个字符串参数的callable,和           返回转换后的值。标准Python类型str,int,           float和complex是这类callables的有用例子。如果没有,           使用str。

  •   
  • default - 如果未指定选项,则生成的值。

  •   
  • const - 指定选项时生成的值和           选项使用不带值的操作。

  •   

parse.add_argument创建Action,使用action参数指定子类。您可以以交互方式或使用以下方式查看此对象:

a = parser.add_argument(....)
print(repr(a))

typenargsdefault等参数存储为此对象的属性。

parse_args操作的某个深度,parser._get_values()最终会在分配给特定操作的每个字符串上调用parser._get_value

def _get_value(self, action, arg_string):
    type_func = self._registry_get('type', action.type, action.type)
    if not callable(type_func):
        msg = _('%r is not callable')
        raise ArgumentError(action, msg % type_func)

    # convert the value to the appropriate type
    try:
        result = type_func(arg_string)

查看字典(parser._registries)以查看是否已定义action.type(作为字符串)。如果不是,则假定action.type本身就是一个函数。 type行中使用了result = type_func(arg_string)

默认None是唯一注册的type

def identity(string):
   return string

argparse.FileType是一个创建type函数的工厂,可以打开文件(即获取文件名并返回打开的文件)。

intfloat内置Python函数,它接受一个字符串并返回一个值,或者在出现问题时引发错误。这些指定了用于转换字符串的函数。它们不直接指定字符串必须表示整数或浮点数。用户有时会以同样的方式错误地使用boolean

action中查找_registries参数。所有默认操作类都有一个条目,因此我们使用storestore_trueappend等值。但我们也可以指定一个自定义的Action类。

至于default,在parse_args堆栈的早期,为每个操作(已定义的参数)执行此行:

setattr(namespace, action.dest, action.default)

这不假设action.default的性质。它可以是None,字符串,数字,列表,函数或任何Python对象。

parse_args的末尾附近,它可以通过action.default功能通过type。仅当default是字符串时才会这样做。

 setattr(namespace, action.dest, self._get_value(action, action.default))

看看你的args。它可能看起来像:

Namespace(integers=['2', '3', '9', '5'], accumulate=max)

由于未指定--sum选项,因此默认值将放在命名空间中而不进行更改或检查。如果您指定了--sum但没有参数,则accumulate=sumconst参数)将位于名称空间中。但--sum some_other_function会创建accumulate="some_other_function"

您选择的type函数会产生打印输入的副作用,但它会使字符串保持不变,因此您会在integers列表中看到字符串。

执行时

args.accumulate(args.integers)

相同
max(["2", "3", "9", "5"])

返回"9" - 字符串,而不是数字。

sum(["2", "3", "9", "5"])

引发错误。错误名称printList仅打印字符串,而不是列表,并且不会将其值转换为整数。

很抱歉长篇大论,但你确实问过发生了什么事。简而言之,编写argparse是为了给用户提供很多功能,但它也试图以简单的默认方式处理许多常见情况。

答案 2 :(得分:0)

因为函数是Python中的第一类对象。它们可以像任何其他类型一样被绑定,访问和移动。

>>> foo = max
>>> foo(2, 3, 1)
3