我想了解此代码的工作原理。为什么可以为type
,const
和default
提供内置函数?
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"得到一个清单? 为什么这样?这就是我想知道的。
答案 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!
如果可能,将从命令行使用一个参数,并且 作为单个项目生产。如果没有命令行参数,则 将生成默认值。请注意,对于可选参数, 还有一个案例 - 选项字符串存在但不存在 然后是命令行参数。在这种情况下,const的值 将被制作。
函数是Python中的第一类对象,可以像任何其他对象一样传递,因此没有理由不能将它们用于const
和default
请注意,如果您实际上 提供了'--sum'
的参数,那么args.accumulate
就是该值:
>>> args = getParser().parse_args(["1", "--sum", "this one"])
('Integer:', '1')
>>> args.accumulate
'this one'
答案 1 :(得分:0)
简短回答:
argparse
期望type
是可调用的(对字符串的限制有限)。
argparse
允许const
和default
几乎任何内容。它不会对它们执行任何操作,除非将它们分配给属性(或将它们传递给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))
type
,nargs
,default
等参数存储为此对象的属性。
在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
函数的工厂,可以打开文件(即获取文件名并返回打开的文件)。
int
,float
内置Python函数,它接受一个字符串并返回一个值,或者在出现问题时引发错误。这些指定了用于转换字符串的函数。它们不直接指定字符串必须表示整数或浮点数。用户有时会以同样的方式错误地使用boolean
。
在action
中查找_registries
参数。所有默认操作类都有一个条目,因此我们使用store
,store_true
和append
等值。但我们也可以指定一个自定义的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=sum
(const
参数)将位于名称空间中。但--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