第一章:Python的数据结构、函数和文件

  • list

    list是一种有序的集合,可以随时添加和删除其中的元素。

    比如,列出班里所有同学的名字,就可以用一个list表示:

>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']
  • 用len()函数可以获得list元素的个数:
>>> len(classmates)
3
  • 用append()函数可以往list中追加元素到末尾:
>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']
  • 用insert()函数可以在特定的位置插入元素:
>>> b_list
['foo', 'peekaboo', 'baz']
>>> b_list.insert(1, 'red')
>>> b_list
O['foo', 'red', 'peekaboo', 'baz']
  • 用pop()函数可以删除list末尾的元素,要删除指定位置的元素,用pop(i)方法,其中i是索引位置:
>>> classmates.pop()
'Adam'
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy']
  • tuple

    另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改。不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

    tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。比如我在tuple里面设置了一个list,我改变这个list是可以的,但是tuple所指向的这个list是永远不会变的。

  • 用tuple可以将任意序列或迭代器转换成元组:

In [5]: tuple([4, 0, 2])
Out[5]: (4, 0, 2)

In [6]: tup = tuple('string')

In [7]: tup
Out[7]: ('s', 't', 'r', 'i', 'n', 'g')
  • 如果你想将元组赋值给类似元组的变量,Python会试图拆分等号右边的值:
In [15]: tup = (4, 5, 6)

In [16]: a, b, c = tup

In [17]: b
Out[17]: 5
  • python允许从元组的开头“摘取”几个元素。它使用了特殊的语法*rest,这也用在函数签名中以抓取任意长度列表的位置参数:
In [29]: values = 1, 2, 3, 4, 5

In [30]: a, b, *rest = values

In [31]: a, b
Out[31]: (1, 2)

In [32]: rest
Out[32]: [3, 4, 5]
  • 用count()函数可以统计某个值得出现频率:
In [34]: a = (1, 2, 2, 2, 3, 4, 2)

In [35]: a.count(2)
Out[35]: 4
  • 用remove()函数会先寻找第一个值并除去:
In [52]: b_list
Out[52]: ['foo', 'red', 'baz', 'dwarf', 'foo']

In [53]: b_list.remove('foo')

In [54]: b_list
Out[54]: ['red', 'baz', 'dwarf', 'foo']
  • 用in()函数可以检查列表是否包含某个值:
In [55]: 'dwarf' in b_list
Out[55]: True
  • 用extend()函数可以追加多个元素:
In [58]: x = [4, None, 'foo']

In [59]: x.extend([7, 8, (2, 3)])

In [60]: x
Out[60]: [4, None, 'foo', 7, 8, (2, 3)]
  • 用sort()函数可以将一个列表原地排序(不创建新的对象):
In [61]: a = [7, 2, 5, 1, 3]

In [62]: a.sort()

In [63]: a
Out[63]: [1, 2, 3, 5, 7]
  • sort()有一些选项,有时会很好用。其中之一是二级排序key,可以用这个key进行排序。例如,我们可以按长度对字符串进行排序:
In [64]: b = ['saw', 'small', 'He', 'foxes', 'six']

In [65]: b.sort(key=len)

In [66]: b
Out[66]: ['He', 'saw', 'six', 'small', 'foxes']
  • bisect模块支持二分查找,和bisect向已排序的列表插入值。bisect.bisect可以找到插入值后仍保证排序的位置,bisect.insort是向这个位置插入值:
In [67]: import bisect

In [68]: c = [1, 2, 2, 2, 3, 4, 7]

In [69]: bisect.bisect(c, 2)
Out[69]: 4

In [70]: bisect.bisect(c, 5)
Out[70]: 6

In [71]: bisect.insort(c, 6)

In [72]: c
Out[72]: [1, 2, 2, 2, 3, 4, 6, 7]
  • 用切边可以选取大多数序列类型的一部分,切片的基本形式是在方括号中使用start:stop。(左闭右开)
In [73]: seq = [7, 2, 3, 7, 5, 6, 0, 1]

In [74]: seq[1:5]
Out[74]: [2, 3, 7, 5]
  • 切片也可以被序列赋值:
In [75]: seq[3:4] = [6, 3]
In [76]: seq
Out[76]: [7, 2, 3, 6, 3, 5, 6, 0, 1]
  • 切片也可以被序列赋值,start和stop都可以被省略,省略之后,分别默认序列的开头和结尾,负数表明从后向前切片。
In [77]: seq[:5]
Out[77]: [7, 2, 3, 6, 3]

In [80]: seq[-6:-2]
Out[80]: [6, 3, 5, 6]
  • 在第二个冒号后面使用step,可以隔一个取一个元素:
In [81]: seq[::2]
Out[81]: [7, 3, 3, 6, 1]
  • 一个聪明的方法是使用-1,它可以将列表或元组颠倒过来:
In [82]: seq[::-1]
Out[82]: [1, 0, 6, 5, 3, 6, 3, 2, 7]
  • 迭代一个序列时,你可能想跟踪当前项的序号,Python内建了一个enumerate函数,可以返回(i,value)元组序列。
for i, value in enumerate(collection):
# 简单来说,这个enumerate就是为collection提供出了一个对应的的value(序列号)。
In [83]: some_list = ['foo', 'bar', 'baz']    #我设置出了一个some_list的list

In [84]: mapping = {}       #而这里我设置出了一个空字典mapping{}

In [85]: for i, v in enumerate(some_list):
   ....:     mapping[v] = i       #而在这里,我就将some_list中的i和value赋予给了字典mapping,其中的i是元素的索引,value是元素的值。
                                  #这里的mapping[v] = i,是一个字典的写法,如mapping[foo] = 0,依次迭代。
In [86]: mapping
Out[86]: {'bar': 1, 'baz': 2, 'foo': 0}
  • sorted函数可以从任意序列的元素返回一个新的排好序的列表:
In [87]: sorted([7, 1, 2, 6, 0, 3, 2])
Out[87]: [0, 1, 2, 2, 3, 6, 7]

In [88]: sorted('horse race')
Out[88]: [' ', 'a', 'c', 'e', 'e', 'h', 'o', 'r', 'r', 's']
  • zip函数可以将多个列表、元组或其它序列成对组合成一个元组列表:
In [89]: seq1 = ['foo', 'bar', 'baz']

In [90]: seq2 = ['one', 'two', 'three']

In [91]: zipped = zip(seq1, seq2)

In [92]: list(zipped)
Out[92]: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]
  • zip可以处理任意多的序列,元素的个数取决于最短的序列:
In [93]: seq3 = [False, True]

In [94]: list(zip(seq1, seq2, seq3))
Out[94]: [('foo', 'one', False), ('bar', 'two', True)]
  • zip的常见用法之一是同时迭代多个序列,可能结合enumerate使用:
In [95]: for i, (a, b) in enumerate(zip(seq1, seq2)):      #我要将zip(seq1,seq2)跟踪当前项的序号,返回(i,(a,b))元组序列,
   ....:     print('{0}: {1}, {2}'.format(i, a, b))        #str.format()函数:格式化字符串的函数,使用方法见下。
   ....:
'''
>>>"{} {}".format("hello", "world")    # 不设置指定位置,按默认顺序
'hello world'
 
>>> "{0} {1}".format("hello", "world")  # 设置指定位置
'hello world'
 
>>> "{1} {0} {1}".format("hello", "world")  # 设置指定位置
'world hello world'
'''
0: foo, one
1: bar, two
2: baz, three
  • 给出一个“被压缩的”序列,zip可以被用来解压序列。也可以当作把行的列表转换为列的列表。这个方法看起来有点神奇:
In [96]: pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clemens'),
   ....:             ('Schilling', 'Curt')]

In [97]: first_names, last_names = zip(*pitchers)

In [98]: first_names
Out[98]: ('Nolan', 'Roger', 'Schilling')

In [99]: last_names
Out[99]: ('Ryan', 'Clemens', 'Curt')
  • reversed()函数可以从后向前迭代一个序列,切记reversed()是一个生成器(后面详细介绍),只有实体化(即列表或for循环)之后才能创建翻转的序列:
In [100]: list(reversed(range(10)))
Out[100]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
  • 字典

    字典可能是Python最为重要的数据结构。它更为常见的名字是哈希映射或关联数组。它是键值对的大小可变集合,键和值都是Python对象。创建字典的方法之一是使用尖括号,用冒号分隔键和值:

In [101]: empty_dict = {}

In [102]: d1 = {'a' : 'some value', 'b' : [1, 2, 3, 4]}

In [103]: d1
Out[103]: {'a': 'some value', 'b': [1, 2, 3, 4]}
  • 你可以像访问列表或元组中的元素一样,访问、插入或设定字典中的元素;可以用检查列表和元组是否包含某个值的方法,检查字典中是否包含某个键;还可以用之前讲过的del关键字或pop方法(返回值的同时删除键)删除值:
In [104]: d1[7] = 'an integer'
In [105]: d1
Out[105]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
In [106]: d1['b']
Out[106]: [1, 2, 3, 4]

In [108]: d1[5] = 'some value'

In [109]: d1
Out[109]: 
{'a': 'some value',
 'b': [1, 2, 3, 4],
 7: 'an integer',
 5: 'some value'}

In [110]: d1['dummy'] = 'another value'

In [111]: d1
Out[111]: 
{'a': 'some value',
 'b': [1, 2, 3, 4],
 7: 'an integer',
 5: 'some value',
 'dummy': 'another value'}

In [112]: del d1[5]

In [113]: d1
Out[113]: 
{'a': 'some value',
 'b': [1, 2, 3, 4],
 7: 'an integer',
 'dummy': 'another value'}

In [114]: ret = d1.pop('dummy')

In [115]: ret
Out[115]: 'another value'

In [116]: d1
Out[116]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
  • key和values是字典的键和值的迭代器方法。虽然键值对没有顺序,这两个方法可以用相同的顺序输出键和值:
In [116]: d1
Out[116]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer'}
In [117]: list(d1.keys())
Out[117]: ['a', 'b', 7]

In [118]: list(d1.values())
Out[118]: ['some value', [1, 2, 3, 4], 'an integer']
  • 用update方法可以将一个字典与另一个融合:
In [119]: d1.update({'b' : 'foo', 'c' : 12})

In [120]: d1
Out[120]: {'a': 'some value', 'b': 'foo', 7: 'an integer', 'c': 12}
  • 常常,你可能想将两个序列配对组合成字典。下面是一种写法:
mapping = {}
for key, value in zip(key_list, value_list):
    mapping[key] = value

因为字典本质上是2元元组的集合,dict可以接受2元元组的列表:

In [121]: mapping = dict(zip(range(5), reversed(range(5))))    
#reversed 函数返回一个反转的迭代器,seq -- 要转换的序列,可以是 tuple, string, list 或 range。

In [122]: mapping
Out[122]: {0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
  • 默认值
posted @ 2022-05-27 13:25  top王  阅读(39)  评论(0编辑  收藏  举报