编写有帮助的函数而不是复杂表达式


Python 简练的语法使得实现了复杂逻辑的单行表达式的书写变得容易。例如,你想从一个URL中解码出查询字符串,这里每一个查询参数代表着一个整形的值:

from urllib.parse import parse_qs
my_value = parse_qs('red=5&blue=0&green=',keep_blank_values=True)
print(repr(my_values))
>>>
{'red': ['5'],'green': [''],'blue': ['0']}

查询字符串的一些参数可能含有多个值,有些可能仅有一个值,有些到目前为止可能是空值,还有些可能根本就没有这个参数。在不同的情况下,对结果集字典使用get方法来处理,将返回不同的对应值。

print('Red:',my_values.get('red'))
print('Green:',my_values.get('green'))
print('Opacity:',my_values.get('opacity'))
>>>
Red: ['5']
Green: ['']
Opacity: None

当一个参数未被提供或者其值为空的时候为其赋值默认值0是一个很好的处理方式。或许你更倾向于使用布尔表达式,因为默认为0从逻辑上看起来,貌似并不能保证所有的情况下都能够适用。

Python的语法使得这个选择变得相当的容易。这的把戏就是空字符串,空列表,零值等都可以被隐式的转换为False值。因此,接下来的表达式中的子表达式为False的时候就会自动的被替换为or 运算符后面的子表达式。

# 查询字符串为:'red=5&blue=0&green='
red = my_value.get('red', [''])[0] or 0
green = my_value.get('green', [''])[0] or 0
opacity = my_value.get('opacity', [''])[0] or 0
print('Red:%r' % red)
print('Green:%r' % green)
print('pacity:%r' % opacity)
>>>
Red: '5'
Green: 0
Opacity: 0

红色判例可以正常的取到值就是因为在my_values这个结果字典中含有这个值。而且是一个带有一个成员:string '5'的列表list值。因此其可以被转换为True,因此or运算符后面的子表达式不会被执行,于是便不会返回0值。

绿色判例返回了0值的原因我们同样可以获悉,在my_values字典中,对应green这个keyvalue是一个带有一个空字符串成员的列表。经过隐式转换即为False,因此or运算符后面的子表达式得以执行,返回零值。

透明度的这个判例返回了0值,原因类似。在my_values字典中对应opacity这个key并没有值。所以按照get方法来运行的话就会返回其表达式的第二个子表达式。默认值就是一个带有一个空字符串成员的列表,于是结果和green判例自然的就保持一致了。

然而,这个表达式不仅难于阅读,还不能满足所有的情况。你还可能想确保返回的数据为数学的整形值,于是还需要手动的为刚才的表达式包装一个内置的函数,来将原本的字符串数据转换成整形的数据,如下:

red = int(my_values.get('red',[''])[0] or 0)

现在,你可能感觉代码更加难理解了。有这么多的视觉噪音干扰着我们的视线。这个方法也变得不在平易近人。一个新读者可能要花费好长时间来分隔语段来分析表达式到底做了什么。即使保持事事务精简很好,但是这并不是要把所有的逻辑都写在一行中。

Python2.5 新添了if/else条件语句和三目表达式 来使得代码更简洁,更清晰。

red = my_values.get('red',[''])
red = int(red[0]) if red[0] else 0

现在好多了吧。对于不太复杂的情况,if/else条件表达式可以使得事情变得更加的美好。但是上面的这个例子并不能完全的用多行的if/else来替代。如果非要这样做的话,你就会看到事情变得更加的糟糕了。

green = my_values.get('gren',[''])
if green[0]:
    green = int(green[0])
else:
    green = 0

为了减少重复代码的出现,现将刚才的这段代码封装一下。

def get_first_int(values,key,default=0):
    found = values.get(key,[''])
    if found[0]:
        found = int(fount[0])
    else:
        found = default
    return found

现在调用这个函数比使用or或者使用了if/else的两行的那段代码变得简单多了。

green = get_first_int(my_values,'green')

当你的表达式开始变得复杂的时候,就是时候考虑一下分隔,重构了。更小的代码块,更多的工具函数。良好的可读性将会给你带来更多。所以,不要让简洁的Python语法成为你复杂脏乱代码的填充物。


备忘录:

  • Python简洁的语法使得编写复杂庞大的单行代码变得更加容易了。
  • 把复杂的表达式重构到工具函数中,尤其是出现重复逻辑的地方更应如此。
  • 布尔表达式(or 或者 in )的一个更好的替代方案就是使用if/else,来增强代码的可读性。

results matching ""

    No results matching ""