解析参数字符串时依赖ValueError是Pythonic吗? 我的具体关切是: 在解析参数时,未来的维护人员理解依赖于抛出错误的代码是否直观 将抛出异常作为服务器的一个理所当然的事情是否代价高昂 默认情况?(看起来可能是根据) 上下文

解析参数字符串时依赖ValueError是Pythonic吗? 我的具体关切是: 在解析参数时,未来的维护人员理解依赖于抛出错误的代码是否直观 将抛出异常作为服务器的一个理所当然的事情是否代价高昂 默认情况?(看起来可能是根据) 上下文,python,Python,我有一个参数counter,用于确定要递增的计数器的名称,并且可以选择递增一个正整数或负整数,该整数与计数器名称之间用=分隔。如果未提供增量值,则增量的默认大小为1。该函数通过分解以逗号分隔的计数器和增量列表来提供,因此整个过程的有效输入可以如下所示: "counter1,counter2=2,counter3=-1" 将“counter1”增加1,将“counter2”增加2,将“counter3”减少1 我最初是怎么写的 这让我震惊,因为我最近回来看它,它过于冗长和笨拙

我有一个参数
counter
,用于确定要递增的计数器的名称,并且可以选择递增一个正整数或负整数,该整数与计数器名称之间用
=
分隔。如果未提供增量值,则增量的默认大小为1。该函数通过分解以逗号分隔的计数器和增量列表来提供,因此整个过程的有效输入可以如下所示:

"counter1,counter2=2,counter3=-1"
将“counter1”增加1,将“counter2”增加2,将“counter3”减少1

我最初是怎么写的 这让我震惊,因为我最近回来看它,它过于冗长和笨拙

这是一种或多或少的Python方式来编码这种行为吗? 通过这些测试用例,我看到:

>>> cparse("byfour=4")
('byfour', 4)
>>> cparse("minusone=-1")
('minusone', -1)
>>> cparse("equalAndNoIncr=")
('equalAndNoIncr', 1)
>>> cparse("noEqual")
('noEqual', 1)
这些测试用例本可以通过我最初编写的方式(如上)捕获,但不会以这种方式捕获:

>>> cparse("twoEquals=2=3")
('twoEquals=2=3', 1)
>>> cparse("missingComma=5missingComma=-5")
('missingComma=5missingComma=-5', 1)
最后一个测试用例不会被任何一种方法捕获。两者都使
int()
呕吐:

>>> cparse("YAmissingComma=5NextCounter")
ValueError: invalid literal for int() with base 10: '5NextCounter'
我很高兴通过问这个问题发现了这个问题。使用该值的服务最终会被它阻塞。我想我可以将函数的一行
return desc,int(mag)
更改为:

    if desc.find("=")<0 and (mag=='0' or (mag if mag.find('..') > -1 else mag.lstrip('-+').rstrip('0').rstrip('.')).isdigit()):
        return desc, int(mag)
    else:
        return 'counterParsingError: {}'.format(desc), 1
如果desc.find(“=”)-1 else mag.lstrip('-+').rstrip('0').rstrip('.').isdigit()):
返回描述,内部(磁)
其他:
返回'counterParsingError:{}'。格式(desc),1

(帽子尖是为了弄清楚这是讨论中最快的方法来确定一个字符串是否是整数)

我会认为是Pythic,尽管你可能更喜欢:

def cparse(counter):
    if "=" not in counter:
        # early exit for this expected case
        return (counter, 1)
    desc, mag = counter.split("=", maxsplit=1)
    # note the use of the optional maxsplit to prevent ValueErrors on "a=b=c"
    # and since we've already tested and short-circuited out of the "no equals" case
    # we can now consider this handled completely without nesting in a try block.
    try:
        mag = int(mag)
    except ValueError:
        # can't convert mag to an int, this is unexpected!
        mag = 1
    return (desc, mag)

您可以对此进行调整,以确保在解析字符串(如
a=b=c
)时获得正确的输出。如果您希望收到
('a',1)
,请保持代码不变。如果您希望<代码>(‘A= B’,1)< /C> >您可以使用<代码>计数器.R拆分< /C> >而不是<代码>计数器.Stule .< /P>我只考虑处理ValueError或此情况,如果解析一个对象可能失败。这里使用它的方式只是因为你获得的列表无法解包而被提升。我不认为它是蟒蛇。同样的原因,如果我们知道我们正在处理的是
None
值,而这些值正好可以进行测试,那么我们就不应该处理AttributeErrors。@JeffMercado如果参数默认为“increment=1”并完全忽略了等于,或者如果参数的格式不正确,则会引发该错误(例如,使用多个等于,或增量中使用非数字字符,或者如果完整的参数字符串在两个计数器值之间缺少逗号)。我最初的做法是显式解析和测试,“foo=3bar=5”缺少一个单元测试用例,其中“bar”之前应该有一个逗号。感谢您的反馈。
    if desc.find("=")<0 and (mag=='0' or (mag if mag.find('..') > -1 else mag.lstrip('-+').rstrip('0').rstrip('.')).isdigit()):
        return desc, int(mag)
    else:
        return 'counterParsingError: {}'.format(desc), 1
def cparse(counter):
    if "=" not in counter:
        # early exit for this expected case
        return (counter, 1)
    desc, mag = counter.split("=", maxsplit=1)
    # note the use of the optional maxsplit to prevent ValueErrors on "a=b=c"
    # and since we've already tested and short-circuited out of the "no equals" case
    # we can now consider this handled completely without nesting in a try block.
    try:
        mag = int(mag)
    except ValueError:
        # can't convert mag to an int, this is unexpected!
        mag = 1
    return (desc, mag)