Python 查漏补缺

在Python中当函数被定义时,默认参数只会运算一次,而不是每次被调用时都会重新运算。

1
2
3
4
5
6
7
8
9
10
11
12
def add_to(num, target=[]):
target.append(num)
return target
add_to(1)
# Output: [1]
add_to(2)
# Output: [1, 2]
add_to(3)
# Output: [1, 2, 3]

你应该永远不要定义可变类型的默认参数,除非你知道你正在做什么。你应该像这样做:

1
2
3
4
5
def add_to(element, target=None):
if target is None:
target = []
target.append(element)
return target

另一种三元运算符:

1
2
#(返回假,返回真)[真或假]
(if_test_is_false, if_test_is_true)[test]

例子:

1
2
3
4
fat = True
fitness = ("skinny", "fat")[fat]
print("Ali is ", fitness)
#输出: Ali is fat

这之所以能正常工作,是因为在Python中,True等于1,而False等于0,这就相当于在元组中使用0和1来选取数据。

上面的例子没有被广泛使用,而且Python玩家一般不喜欢那样,因为没有Python味儿(Pythonic)。这样的用法很容易把真正的数据与true/false弄混。

另外一个不使用元组条件表达式的缘故是因为在元组中会把两个条件都执行,而 if-else 的条件表达式不会这样。

例如:

1
2
3
4
5
6
condition = True
print(2 if condition else 1/0)
#输出: 2
print((1/0, 2)[condition])
#输出ZeroDivisionError异常

这是因为在元组中是先建数据,然后用True(1)/False(0)来索引到数据。 而if-else条件表达式遵循普通的if-else逻辑树, 因此,如果逻辑中的条件异常,或者是重计算型(计算较久)的情况下,最好尽量避免使用元组条件表达式。


当你在一个字典中对一个键进行嵌套赋值时,如果这个键不存在,会触发keyError异常。 defaultdict允许我们用一个聪明的方式绕过这个问题。 首先我分享一个使用dict触发KeyError的例子,然后提供一个使用defaultdict的解决方案。

问题:

1
2
3
4
some_dict = {}
some_dict['colours']['favourite'] = "yellow"
## 异常输出:KeyError: 'colours'

解决方案:

1
2
3
4
5
6
import collections
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
## 运行正常

你可以用json.dumps打印出some_dict,例如:

1
2
3
4
import json
print(json.dumps(some_dict))
## 输出: {"colours": {"favourite": "yellow"}}

列表辗平

您可以通过使用itertools包中的itertools.chain.from_iterable轻松快速的辗平一个列表。下面是一个简单的例子:

1
2
3
4
5
6
7
a_list = [[1, 2], [3, 4], [5, 6]]
print(list(itertools.chain.from_iterable(a_list)))
# Output: [1, 2, 3, 4, 5, 6]
# or
print(list(itertools.chain(*a_list)))
# Output: [1, 2, 3, 4, 5, 6]

待续