Python argparse不';t强制转换默认的数值参数?

Python argparse不';t强制转换默认的数值参数?,python,python-2.7,argparse,Python,Python 2.7,Argparse,有些代码行抵得上千言万语。使用以下内容创建python文件test.py: import argparse parser = argparse.ArgumentParser() parser.add_argument('--G', type=float, default=1, nargs='?') args = parser.parse_args() print (args.G / 3) 然后,在终端中: python test.py 给出0,同时: python test.py --G 1

有些代码行抵得上千言万语。使用以下内容创建python文件
test.py

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--G', type=float, default=1, nargs='?')
args = parser.parse_args()
print (args.G / 3)
然后,在终端中:

python test.py
给出
0
,同时:

python test.py --G 1
给出
0.333333
。我认为这是因为
argparse
似乎没有将
default
参数转换为其正确的类型(因此
1
default=1
中仍然是
int
,尽管
type=float
),但如果显式给出,它会转换参数


我认为这是不一致的,而且容易出错。
argparse
这样做有什么原因吗?

我认为
default=1
中的
1
在调用
parser.add_argument
时进行计算,其中作为参数传递的非默认值在运行时进行计算,因此可以通过argparse转换为float。这不是argparse的行为方式;这是python通常的行为方式。考虑这个

def foo(x=1):
    # there is no way to tell the function body that you want 1.0
    # except for explicitly conversion
    # because 1 is passed by value, which has already been evaluated
    # and determined to be an int
    print (x/3)
大编辑:哈,我现在理解你的观点,我认为这是合理的。因此,我深入研究了源代码,看看我发现了什么:

因此,只要是字符串,
argparse
就可以确保默认值符合类型。尝试:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--G', type=float, default='1', nargs='?')
args = parser.parse_args()
print (args.G / 3)

不确定这是错误还是妥协…

我认为
default=1
中的
1
是在调用
解析器时计算的。添加_argument
,其中作为参数传递的非默认值是在运行时计算的,因此可以通过argparse转换为float。这不是argparse的行为方式;这是python通常的行为方式。考虑这个

def foo(x=1):
    # there is no way to tell the function body that you want 1.0
    # except for explicitly conversion
    # because 1 is passed by value, which has already been evaluated
    # and determined to be an int
    print (x/3)
大编辑:哈,我现在理解你的观点,我认为这是合理的。因此,我深入研究了源代码,看看我发现了什么:

因此,只要是字符串,
argparse
就可以确保默认值符合类型。尝试:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--G', type=float, default='1', nargs='?')
args = parser.parse_args()
print (args.G / 3)

不确定这是错误还是妥协…

键入
的目的是对从命令行接收到的任意输入进行清理和验证。这是防止虚假输入的第一道防线。没有必要针对
默认值为自己“辩护”,因为这是您自己决定的值,您有权完全控制您的应用程序
type
并不意味着
parse_args()
之后的结果值必须是该类型;这意味着任何输入都应该是该类型/应该是该函数的结果

默认值是什么完全独立于此,完全取决于您。完全可以想象,
default
值为
False
,如果用户为这个可选参数输入一个数字,那么它将改为一个数字

将下面的评论升级到此处:Python的理念包括“每个人都是负责任的成年人,Python不会过度质疑您的决定”(意译)。我认为这在这里非常适用


argparse
确实转换了
default
字符串,这一事实可以解释为CLI输入始终是一个字符串,并且可能链接了多个argparser,
default
值是由以前的输入设置的。但是,非字符串类型的任何内容都必须由您明确选择,因此不会进一步损坏。

类型的目的是清理和验证从命令行接收的任意输入。这是防止虚假输入的第一道防线。没有必要针对
默认值为自己“辩护”,因为这是您自己决定的值,您有权完全控制您的应用程序
type
并不意味着
parse_args()
之后的结果值必须是该类型;这意味着任何输入都应该是该类型/应该是该函数的结果

默认值是什么完全独立于此,完全取决于您。完全可以想象,
default
值为
False
,如果用户为这个可选参数输入一个数字,那么它将改为一个数字

将下面的评论升级到此处:Python的理念包括“每个人都是负责任的成年人,Python不会过度质疑您的决定”(意译)。我认为这在这里非常适用


argparse
确实转换了
default
字符串,这一事实可以解释为CLI输入始终是一个字符串,并且可能链接了多个argparser,
default
值是由以前的输入设置的。但是,任何不是字符串类型的内容都必须由您明确选择,这样它就不会被进一步损坏。

其他答案是正确的-只有字符串默认值通过
type
函数传递。但似乎有些人不愿接受这种逻辑

也许这个例子会有帮助:

import argparse
def mytype(astring):
    return '['+astring+']'
parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=mytype, default=1)
parser.add_argument('--bar', type=mytype, default='bar')
print parser.parse_args([])
print mytype(1)
产生:

0923:~/mypy$ python stack35429336.py 
Namespace(bar='[bar]', foo=1)
Traceback (most recent call last):
  File "stack35429336.py", line 8, in <module>
    print mytype(1)
  File "stack35429336.py", line 3, in mytype
    return '['+astring+']'
TypeError: cannot concatenate 'str' and 'int' objects
type=bool
是常见错误
bool()
不会将字符串
'False'
转换为布尔值
False

In [50]: bool('False')
Out[50]: True
如果
argparse
通过
type
函数传递每个默认值,则很难将
None
False
等值放置在
命名空间中。没有内置函数将字符串转换为
None

关键点在于
type
参数是一个函数(
可调用的
),而不是强制转换操作或目标


如需进一步澄清或混淆,请使用
nargs=2
action='append'
探索
默认值
类型
,其他答案正确-只有字符串默认值通过
类型
函数传递。但似乎有些人不愿接受这种逻辑

也许吧