Python 解决问题的方式经常会随着时间的推移而发生改变。随着Python的演变,Python列表的计数方式也得到了发展。
对列表中各项目进行计数有各种各样的方法,接下来我们将通过观察每一种方法的代码风格,来分析这些技术的不同之处。至于它们的性能,我们以后再考虑。
我们需要了解一些 Python 的历史来理解这些不同的方法。幸运的是,我们可以用 Python 的 __future__ 模块,坐上时光机。现在让我们坐上德罗瑞恩(注:即系列电影《回到未来》中的时间机器),驶向1997年。
if 语句
现在是 1997 年 1 月,我们使用的是 Python 1.4。有一个颜色列表,我们很想要知道每一种颜色分别出现了多少次。我们来使用字典看看。
1 2 3 4 5 6 7 |
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: if color_counts.has_key(c): color_counts[c] = color_counts[c] + 1 else: color_counts[c] = 1 |
注:我们没有用+=,因为增量赋值语句在 Python2.0 版之后才被添加进去。我们也没有使用 c in color_counts 语句,因为这个语句到 Python2.2 版本才可以使用。
运行上述代码后,我们可以看到 color_counts 字典里包含了每一种颜色出现的次数。
1 2 |
>>> color_counts {'brown': 3, 'yellow': 2, 'green': 1, 'black': 1, 'red': 1} |
这段代码很简单。通过循环遍历每一种颜色,检查每种颜色是否已经出现在字典中,如果还没有,把它添加到字典中。如果已经出现,那么把它的数量增一。
我们也可以按照下面的方式来写:
1 2 3 4 5 6 |
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: if not color_counts.has_key(c): color_counts[c] = 0 color_counts[c] = color_counts[c] + 1 |
对于稀疏列表(没有很多重复颜色的列表),这种方式也许会有一点点慢,因为在 for 循环里需要执行两条语句。但是我们不担心它的性能,我们考虑的是它的代码风格。深思熟虑之后,我们决定使用新版本的代码。
试试块语句
现在是 1997 年 1 月 2 日,我们仍然在使用 Python 1.4。某天的早晨,我们醒来后突然意识到,我们本来应该按照“先斩后奏” 的方式去实践(这种方式更符合 Python 的思想),但实际上,我们是按照“三思而后行”的想法在编写代码。现在按照“先斩后奏”的方式,把我们的代码重写成一个 try-except 的块语句:
1 2 3 4 5 6 7 |
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: try: color_counts[c] = color_counts[c] + 1 except KeyError: color_counts[c] = 1 |
这段代码试着为每一种颜色的数量增一,但是如果这种颜色还没有出现在字典中,就会产生 KeyError 错误,那么该种颜色的数量就被初始化为 1。
get 方法
现在是 1998 年 1 月 1 日,Python 已经升级到 1.5 版本。我们决定用字典中的 get 方法来重写代码。
1 2 3 4 |
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: color_counts[c] = color_counts.get(c, 0) + 1 |
这段代码循环遍历每一种颜色,每次循环从字典中获得当前颜色的计数,默认计数为零,然后计数加一,最后把新值赋给这个字典的键,也就是颜色。
这段代码很棒的是 for 循环里只有一行语句,但是我们并不确定这是不是更加符合 Python 的风格。我们觉得也许这次的改进显得太智能了,所以我们决定将这次的改进还原。
setdefault 方法
现在是 2001 年 1 月,我们已经在使用 Python 2.0 版。在 Python 2.0 版中,字典里新添加了 setdefault 的方法。于是我们决定用 setdefault 的方法和 += 的增量运算符来重写代码:
1 2 3 4 5 |
colors = [
colors = [div> Python 解决问题的方式经常会随着时间的推移而发生改变。随着Python的演变,Python列表的计数方式也得到了发展。 对列表中各项目进行计数有各种各样的方法,接下来我们将通过观察每一种方法的代码风格,来分析这些技术的不同之处。至于它们的性能,我们以后再考虑。 我们需要了解一些 Python 的历史来理解这些不同的方法。幸运的是,我们可以用 Python 的 __future__ 模块,坐上时光机。现在让我们坐上德罗瑞恩(注:即系列电影《回到未来》中的时间机器),驶向1997年。 if 语句现在是 1997 年 1 月,我们使用的是 Python 1.4。有一个颜色列表,我们很想要知道每一种颜色分别出现了多少次。我们来使用字典看看。
注:我们没有用+=,因为增量赋值语句在 Python2.0 版之后才被添加进去。我们也没有使用 c in color_counts 语句,因为这个语句到 Python2.2 版本才可以使用。 运行上述代码后,我们可以看到 color_counts 字典里包含了每一种颜色出现的次数。
这段代码很简单。通过循环遍历每一种颜色,检查每种颜色是否已经出现在字典中,如果还没有,把它添加到字典中。如果已经出现,那么把它的数量增一。 我们也可以按照下面的方式来写:
对于稀疏列表(没有很多重复颜色的列表),这种方式也许会有一点点慢,因为在 for 循环里需要执行两条语句。但是我们不担心它的性能,我们考虑的是它的代码风格。深思熟虑之后,我们决定使用新版本的代码。 试试块语句现在是 1997 年 1 月 2 日,我们仍然在使用 Python 1.4。某天的早晨,我们醒来后突然意识到,我们本来应该按照“先斩后奏” 的方式去实践(这种方式更符合 Python 的思想),但实际上,我们是按照“三思而后行”的想法在编写代码。现在按照“先斩后奏”的方式,把我们的代码重写成一个 try-except 的块语句:
这段代码试着为每一种颜色的数量增一,但是如果这种颜色还没有出现在字典中,就会产生 KeyError 错误,那么该种颜色的数量就被初始化为 1。 get 方法现在是 1998 年 1 月 1 日,Python 已经升级到 1.5 版本。我们决定用字典中的 get 方法来重写代码。
这段代码循环遍历每一种颜色,每次循环从字典中获得当前颜色的计数,默认计数为零,然后计数加一,最后把新值赋给这个字典的键,也就是颜色。 这段代码很棒的是 for 循环里只有一行语句,但是我们并不确定这是不是更加符合 Python 的风格。我们觉得也许这次的改进显得太智能了,所以我们决定将这次的改进还原。 setdefault 方法现在是 2001 年 1 月,我们已经在使用 Python 2.0 版。在 Python 2.0 版中,字典里新添加了 setdefault 的方法。于是我们决定用 setdefault 的方法和 += 的增量运算符来重写代码:
|