编写python风格的代码(1)| 遍历、基本数据类型、列表解析

摘自提姆·彼得斯(Tim Peters)的《 Python的禅宗》:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Readability counts.

美丽胜于丑陋。
显式胜于隐式。
简单胜于复杂。
可读性很重要。


1.遍历

惯用方式编码的好处:提高代码的复用性和可读性

(1) 遍历一个列表
z = [ 'a', 'b', 'c', 'd' ]

最明智的做法是使用enumerate,简单并且可读

>>> for i, item in enumerate(z):
...    print i, item
0 a
1 b
2 c
3 d
(2) 对于文件内容的遍历
>>> for line in open('data/listfile.txt'):
...    print line.rstrip()
a
b
c
d

2.一些基本数据类型的使用

(1)元组

首先是最熟悉的元组,隐式使用元组交换两个数字:

>>> a = 5
>>> b = 6
>>> a, b = b, a
>>> print a == 6, b == 5
True True

以上是关于元组的所有内容

(2)列表

列表和字典的使用

>>> x = []
>>> x.append(5)
>>> x.extend([6, 7, 8])
>>> x
[5, 6, 7, 8]
>>> x.reverse()
>>> x
[8, 7, 6, 5]

排序也很容易,考虑这样的数据集:

y = [ ('IBM', 5), ('Zil', 3), ('DEC', 18) ]

sort方法会对每一个元组执行cmp方法,在每个元组的第一个元素上进行排序:

>>> y.sort()
>>> y
[('DEC', 18), ('IBM', 5), ('Zil', 3)]

在元组的不同元素上进行排序也很方便,有几种方法可以实现,我通常使用自己实现的方法:

>>> def sort_on_second(a, b):
...   return cmp(a[1], b[1])

>>> y.sort(sort_on_second)
>>> y
[('Zil', 3), ('IBM', 5), ('DEC', 18)]

请注意,这里我使用内置cmp方法(sort 默认情况下使用的方法:y.sort()等效于y.sort(cmp))对元组的第二个元素进行比较。

(3)字典

基本的字典就是一个哈希表,哈希表通过获取键来返回值。

>>> d  =  {} 
>>> d [ 'a' ]  =  5 
>>> d [ 'b' ]  =  4 
>>> d [ 'c' ]  =  18 
>>> d 
{'a'5'c'18'b'4} 
>>> d [ 'a' ] 
5

可以使用dict类型初始化字典以创建dict对象:

>>> e  =  dict (a = 5 , b = 4 , c = 18>>> e 
{'a'5'c'18'b'4}

让我们收集(键,值)对,其中每个键可能具有多个值。也就是说,给定一个包含此数据的文件:

a 5
b 6
d 7
a 2
c 1

假设我们要保留所有值?如果我们只是简单地做到这一点,

>>> d = {}
>>> for line in file('data/keyvalue.txt'):
...   key, value = line.split()
...   d[key] = int(value)

这样会丢失第一个值

>>> d 
{'a'2'c'1'b'6'd'7}

可以使用get方法收集所有的值

>>> d = {}
>>> for line in file('data/keyvalue.txt'):
...   key, value = line.split()
...   l = d.get(key, [])
...   l.append(int(value))
...   d[key] = l
>>> d
{'a': [5, 2], 'c': [1], 'b': [6], 'd': [7]}

这里的d.get(k, default)等同于d[k] if d[k] already exists; otherwise, it returns default.
因此,第一遍的时候所有的key都使用完了。
l被设置为一个空的list,值被append到这个list,然后把值对应到key。

现在,让我们尝试将上面的一些排序内容与字典结合起来。这次,我们的人为问题是我们想对d刚加载的字典进行排序,我们希望按每个键的值之和排序,而不是按键排序。
先定义一个排序方法:

>>> def sort_by_sum_value(a, b):
...    sum_a = sum(a[1])
...    sum_b = sum(b[1])
...    return cmp(sum_a, sum_b)

然后把它应用到字典上,

>>> items = d.items()
>>> items
[('a', [5, 2]), ('c', [1]), ('b', [6]), ('d', [7])]
>>> items.sort(sort_by_sum_value)
>>> items
[('c', [1]), ('b', [6]), ('a', [5, 2]), ('d', [7])]

3.列表解析

列表解析可以缩短代码行,这是一个产生0-4之间平方数的列表的例子,

>>> z = [ i**2 for i in range(0, 5) ]
>>> z
[0, 1, 4, 9, 16]

还可以添加条件,比如只需要偶数

>>> z = [ i**2 for i in range(0, 10) if i % 2 == 0 ]
>>> z
[0, 4, 16, 36, 64]

一般形式是:[ expression for var in list if conditional ]
所以你有很多选择去expression和conditional。

列表解析对于文件解析和简单数学都非常有用。考虑一个包含数据和注释的文件:

# this is a comment or a header
1
# another comment
2

如果你只想读取其中的数字

>>> data = [ int(x) for x in open('data/commented-data.txt') if x[0] != '#' ]
>>> data
[1, 2]

这样做简短、简单、明确。

对于简单的数学计算也可以使用列表解析,比如计算一些数据的均值和方差:

>>> import math
>>> data = [ 1, 2, 3, 4, 5 ]
>>> average = sum(data) / float(len(data))
>>> stddev = sum([ (x - average)**2 for x in data ]) / float(len(data))
>>> stddev = math.sqrt(stddev)
>>> print average, '+/-', stddev
3.0 +/- 1.41421356237

如果列表解析的长度大于一行请使用for循环,这样更易读易懂。

猜你喜欢

转载自blog.csdn.net/qq_30262201/article/details/103957143