Python 解决问题的方式经常会随着时间的推移而发生改变。随着Python的演变,Python列表的计数方式也得到了发展。
对列表中各项目进行计数有各种各样的方法,接下来我们将通过观察每一种方法的代码风格,来分析这些技术的不同之处。至于它们的性能,我们以后再考虑。
我们需要了解一些 Python 的历史来理解这些不同的方法。幸运的是,我们可以用 Python 的 __future__ 模块,坐上时光机。现在让我们坐上德罗瑞恩(注:即系列电影《回到未来》中的时间机器),驶向1997年。
现在是 1997 年 1 月,我们使用的是 Python 1.4。有一个颜色列表,我们很想要知道每一种颜色分别出现了多少次。我们来使用字典看看。
1234567 | 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 字典里包含了每一种颜色出现的次数。
12 | >>> color_counts{\’brown\’: 3, \’yellow\’: 2, \’green\’: 1, \’black\’: 1, \’red\’: 1} |
这段代码很简单。通过循环遍历每一种颜色,检查每种颜色是否已经出现在字典中,如果还没有,把它添加到字典中。如果已经出现,那么把它的数量增一。
我们也可以按照下面的方式来写:
123456 | 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 的块语句:
1234567 | 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。
现在是 1998 年 1 月 1 日,Python 已经升级到 1.5 版本。我们决定用字典中的 get 方法来重写代码。
1234 | 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 的风格。我们觉得也许这次的改进显得太智能了,所以我们决定将这次的改进还原。
现在是 2001 年 1 月,我们已经在使用 Python 2.0 版。在 Python 2.0 版中,字典里新添加了 setdefault 的方法。于是我们决定用 setdefault 的方法和 += 的增量运算符来重写代码:
12345 | 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 的方法和 += 的增量运算符来重写代码:
|