繁体   English   中英

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

[英]Why can you assign functions to type, const and default?

我想了解为什么此代码有效。 为什么要给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”,因为您只想允许Integers。 所以你给“类型”一些东西。 但是在我的示例中,“类型”为“ printList”函数提供了一些功能,以便可以打印它。 或例如“默认”。 我希望给出一些值,例如int或str。 我给“默认”的东西。 但是在我的示例中,我给内置函数“ max”。 为什么“ max”获得列表? 为什么行得通? 这就是我想知道的。

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

是,假设你不提供与参数'--sum' ,像一点点

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

根据nargs='?'

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

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


请注意,如果您确实提供了带有'--sum'的参数,则args.accumulate将是该值:

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

简短答案:

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

argparse允许constdefault几乎是任何东西。 除了将它们分配给属性(或将它们传递给可调用的type )之外,它对它们没有任何作用。

长答案:

在内部文档中,对于class Action

  • 类型-可调用的类型,它接受单个字符串参数,并返回转换后的值。 标准的Python类型str,int,float和complex是此类可调用对象的有用示例。 如果为None,则使用str。

  • 默认值-如果未指定该选项,则将产生的值。

  • const-如果指定了选项并且选项使用不带值的操作,则将产生的值。

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

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

typenargsdefault这样的参数都存储为该对象的属性。

parse_args操作的某个深度parse_argsparser._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 (作为字符串)。 如果不是,则假定action.type本身是一个函数。 type用于result = type_func(arg_string)行。

默认情况下, None是唯一注册的type

def identity(string):
   return string

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

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

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

对于default ,在parse_args堆栈的早期,对每个操作(定义的参数)执行以下行:

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

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

parse_args的结尾附近,它可能通过type函数传递action.default 仅当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可以为用户提供很多功能,但是它也尝试以一种简单的默认方式来处理许多常见情况。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM