2017-10-21 24 views
1

我的具体问题是

  1. 当解析一个参数,它是直观未来的维护者理解代码依赖于抛出一个错误?
  2. 默认情况下抛出异常是否很昂贵? (好像它可能根据https://stackoverflow.com/a/9859202/776940

语境

我有一个参数counter其确定计数器的名称来递增,并且任选地可以通过从计数器分离的正或负整数递增名字由=。如果没有提供增值,增量的默认大小为1。功能是通过破坏一个逗号分隔的计数器和增量的名单反馈的信息,有效的投入到整个过程是这样的:解析参数字符串时PyEronic是否依赖ValueError?

"counter1,counter2=2,counter3=-1" 

这将增加“C1的”加1,加1

我最初是如何写的

counterDescriptor = counterValue.split('=') 
if len(counterDescriptor) == 1: 
    counterName = counterDescriptor[0] 
    counterIncr = 1 
elif len(counterDescriptor) == 2: 
    counterName = counterDescriptor[0] 
    counterIncr = int(counterDescriptor[1]) 
else: 
    counterName, counterIncr = ('counterParsingError', 1) 

它给我的印象,因为我最近回到2和减量“C3的”增量“计数器2”看看它,过于冗长和笨重。

这是一个或多或少Pythonic的方式来编码的行为?

def cparse(counter): 
    try: 
     desc,mag = counter.split('=') 
    except ValueError: 
     desc = counter 
     mag = '' 
    finally: 
     if mag == '': 
      mag = 1 
    return desc, int(mag) 

利用这些测试用例,我看到:

>>> 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 

(帽尖到https://stackoverflow.com/a/9859202/776940搞清楚,这是在讨论提供了最快的方式确定一个字符串为整数)

+1

我只会考虑处理ValueErrors或这种情况下,如果解析对象可能会失败。它在这里被使用的方式只是因为你获得的列表不能被解压缩。我不会认为它pythonic。同样的原因,如果我们知道我们正在处理“无”值时,我们就不应该处理AttributeErrors。 –

+0

@JeffMercado如果参数默认为'increment = 1',并且完全脱离等于,或者参数格式错误(例如,多个等于或在增量中带有非数字字符或如果完整的参数串缺少两个计数器值之间的逗号)。我最初的做法是明确解析和测试,而且我错过了'foo = 3bar = 5'的单元测试用例,在'bar'之前应该有一个逗号。感谢您的反馈。 –

回答

2

我认为Python的,虽然你也许对这喜欢:

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),您可以使用counter.rsplit而不是counter.split