1.2.2.2 容器

Python提供了许多有效的容器类型,其中存储了对象集合。

1.2.2.2.1 列表

列表是一个有序的对象集合,对象可以有多种类型。例如:

In [28]:

  1. L = ['red', 'blue', 'green', 'black', 'white']
  2. type(L)

Out[28]:

  1. list

索引:访问包含在列表中的单个对象:

In [29]:

  1. L[2]

Out[29]:

  1. 'green'

使用负索引,从结尾开始计数:

In [30]:

  1. L[-1]

Out[30]:

  1. 'white'

In [31]:

  1. L[-2]

Out[31]:

  1. 'black'

注意:索引从0开始(和C中一样),而不是1(像在Fortran或Matlab)!

切片:获得规律分布元素的子列表:

In [32]:

  1. L

Out[32]:

  1. ['red', 'blue', 'green', 'black', 'white']

In [33]:

  1. L[2:4]

Out[33]:

  1. ['green', 'black']

注意:L[start:stop]包含索引start<= i < stop的元素(i的范围从start到stop-1)。因此,L[start:stop]包含(stop-start)个元素。

切片语法L[start:stop:stride]

所有切片参数都是可选的:

In [34]:

  1. L

Out[34]:

  1. ['red', 'blue', 'green', 'black', 'white']

In [35]:

  1. L[3:]

Out[35]:

  1. ['black', 'white']

In [36]:

  1. L[:3]

Out[36]:

  1. ['red', 'blue', 'green']

列表是可变对象,可以被改变:

In [38]:

  1. L[0] = 'yellow'
  2. L

Out[38]:

  1. ['yellow', 'blue', 'green', 'black', 'white']

In [39]:

  1. L[2:4] = ['gray', 'purple']
  2. L

Out[39]:

  1. ['yellow', 'blue', 'gray', 'purple', 'white']

注:一个列表的元素可以有不同的类型:

In [40]:

  1. L = [3, -200, 'hello']
  2. L

Out[40]:

  1. [3, -200, 'hello']

In [41]:

  1. L[1], L[2]

Out[41]:

  1. (-200, 'hello')

对于一个所有类型都相同的数值数据集合,使用Numpy模块提供的数组类型通常更有效。Numpy数组是包含固定大小项目的内存组块。使用Numpy数组,元素上的操作可以非常快速,因为元素均匀分布在内存上并且更多的操作是通过特殊的C函数而不是Python循环。

Python提供了一大组函数来修改或查询列表。这里是一些例子,更多内容,请见:http://docs.python.org/tutorial/datastructures.html#more-on-lists

添加和删除元素:

In [42]:

  1. L = ['red', 'blue', 'green', 'black', 'white']
  2. L.append('pink')
  3. L

Out[42]:

  1. ['red', 'blue', 'green', 'black', 'white', 'pink']

In [43]:

  1. L.pop() # 删除并返回最后一个项目

Out[43]:

  1. 'pink'

In [44]:

  1. L

Out[44]:

  1. ['red', 'blue', 'green', 'black', 'white']

In [45]:

  1. L.extend(['pink', 'purple']) # 扩展列表L,原地
  2. L

In [46]:

  1. L = L[:-2]
  2. L

Out[46]:

  1. ['red', 'blue', 'green', 'black', 'white']

反转:

In [47]:

  1. r = L[::-1]
  2. r

Out[47]:

  1. ['white', 'black', 'green', 'blue', 'red']

In [48]:

  1. r2 = list(L)
  2. r2

Out[48]:

  1. ['red', 'blue', 'green', 'black', 'white']

In [49]:

  1. r2.reverse() # 原对象
  2. r2

Out[49]:

  1. ['white', 'black', 'green', 'blue', 'red']

串联和重复列表:

In [50]:

  1. r + L

Out[50]:

  1. ['white',
  2. 'black',
  3. 'green',
  4. 'blue',
  5. 'red',
  6. 'red',
  7. 'blue',
  8. 'green',
  9. 'black',
  10. 'white']

In [51]:

  1. r * 2

Out[51]:

  1. ['white',
  2. 'black',
  3. 'green',
  4. 'blue',
  5. 'red',
  6. 'white',
  7. 'black',
  8. 'green',
  9. 'blue',
  10. 'red']

排序:

In [52]:

  1. sorted(r) # 新对象

Out[52]:

  1. ['black', 'blue', 'green', 'red', 'white']

In [53]:

  1. r

Out[53]:

  1. ['white', 'black', 'green', 'blue', 'red']

In [55]:

  1. r.sort() # 原对象
  2. r

Out[55]:

  1. ['black', 'blue', 'green', 'red', 'white']

方法和面向对象编程

符号r.method() (即 r.append(3) and L.pop()) 是我们第一个关于面向对象编程的例子(OOP)。作为列表,对象r有可以以这种方式调用的方法函数。对于这篇教程不需要关于面向对象编程的更多知识,只需要理解这种符号。

发现方法

提醒:在IPython中:tab完成 (按tab)

  1. In [28]: r.<TAB>
  2. r.__add__ r.__iadd__ r.__setattr__
  3. r.__class__ r.__imul__ r.__setitem__
  4. r.__contains__ r.__init__ r.__setslice__
  5. r.__delattr__ r.__iter__ r.__sizeof__
  6. r.__delitem__ r.__le__ r.__str__
  7. r.__delslice__ r.__len__ r.__subclasshook__
  8. r.__doc__ r.__lt__ r.append
  9. r.__eq__ r.__mul__ r.count
  10. r.__format__ r.__ne__ r.extend
  11. r.__ge__ r.__new__ r.index
  12. r.__getattribute__ r.__reduce__ r.insert
  13. r.__getitem__ r.__reduce_ex__ r.pop
  14. r.__getslice__ r.__repr__ r.remove
  15. r.__gt__ r.__reversed__ r.reverse
  16. r.__hash__ r.__rmul__ r.sort

1.2.2.2.2 字符

不同的字符语法(单引号、双引号或三个引号):

In [58]:

  1. s = 'Hello, how are you?'
  2. s = "Hi, what's up"
  3. s = '''Hello,
  4. how are you''' # 三个引号可以允许字符跨行
  5. s = """Hi,
  6. what's up?"""
  7. 'Hi, what's up?'
  1. File "<ipython-input-58-dfe00f996c26>", line 7
  2. 'Hi, what's up?'
  3. ^
  4. SyntaxError: invalid syntax

如果在字符中要是使用引号,那么应该嵌套使用,或者使用"\"进行转义,否则会报错。

换行的符号为 \n,tab符号是\t。

字符也是类似与列表的结合。因此,也可以使用相同的语法和规则索引和切片。

索引:

In [59]:

  1. a = "hello"
  2. a[0]

Out[59]:

  1. 'h'

In [60]:

  1. a[1]

Out[60]:

  1. 'e'

In [61]:

  1. a[-1]

Out[61]:

  1. 'o'

(记住负索引从右侧开始计数。)

切片:

In [64]:

  1. a = "hello, world!"
  2. a[3:6] # 第三到第六个(不包含)元素:元素3、4、5

Out[64]:

  1. 'lo,'

In [65]:

  1. a[2:10:2] # 语法:a[开始:结束:步幅]

Out[65]:

  1. 'lo o'

In [66]:

  1. a[::3] # 从开始到结尾,每隔3个字母

Out[66]:

  1. 'hl r!'

重音符号和特殊字符也可以被处理为Unicode字符(请见 http://docs.python.org/tutorial/introduction.html#unicode-strings)。

字符是不可变对象,不可能修改内容。不过可以从原始的字符中创建一个新的字符。

In [68]:

  1. a = "hello, world!"
  2. a[2] = 'z'
  1.  ------------- ------------- ------------- ------------- -----------------------
  2. TypeError Traceback (most recent call last)
  3. <ipython-input-68-8f124c87c8cf> in <module>()
  4. 1 a = "hello, world!"
  5. ----> 2 a[2] = 'z'
  6. TypeError: 'str' object does not support item assignment

In [69]:

  1. a.replace('l', 'z', 1)

Out[69]:

  1. 'hezlo, world!'

In [70]:

  1. a.replace('l', 'z')

Out[70]:

  1. 'hezzo, worzd!'

字符有许多有用的方法,比如上面的a.replace。回忆一下a.面向对象的符号,并且使用tab完成或者help(str)来搜索新的方法。and use tab completion or

更多内容 Python提供了操作的字符的高级可能性,看一下模式或格式。感兴趣的读者请参考:http://docs.python.org/library/stdtypes.html#string-methodshttp://docs.python.org/library/string.html#new-string-formatting。

字符格式:

In [71]:

  1. 'An integer: %i; a float: %f; another string: %s' % (1, 0.1, 'string')

Out[71]:

  1. 'An integer: 1; a float: 0.100000; another string: string'

In [72]:

  1. i = 102
  2. filename = 'processing_of_dataset_%d.txt' % i
  3. filename

Out[72]:

  1. 'processing_of_dataset_102.txt'

1.2.2.2.3. Dictionaries

字典本质上是一个映射键值的高效表格。它是一个无序的容器

In [74]:

  1. tel = {'emmanuelle': 5752, 'sebastian': 5578}
  2. tel['francis'] = 5915
  3. tel

Out[74]:

  1. {'emmanuelle': 5752, 'francis': 5915, 'sebastian': 5578}

In [75]:

  1. tel['sebastian']

Out[75]:

  1. 5578

In [76]:

  1. tel.keys()

Out[76]:

  1. ['sebastian', 'francis', 'emmanuelle']

In [77]:

  1. tel.values()

Out[77]:

  1. [5578, 5915, 5752]

它可以方便的以名字(日期的字符和名称等)存储和获取值。更多信息见 http://docs.python.org/tutorial/datastructures.html#dictionaries。

一个字典的键(代表值)可以有不同的类型:

In [78]:

  1. d = {'a':1, 'b':2, 3:'hello'}
  2. d

Out[78]:

  1. {3: 'hello', 'a': 1, 'b': 2}

1.2.2.2.4. More container types

元组

元组本质上是不可变列表。元组的元素用括号包起来,或者只是用逗号分割:

In [79]:

  1. t = 12345, 54321, 'hello!'
  2. t[0]

Out[79]:

  1. 12345

In [80]:

  1. t

Out[80]:

  1. (12345, 54321, 'hello!')

In [81]:

  1. u = (0, 2)

集合:无序,惟一项目:

In [82]:

  1. s = set(('a', 'b', 'c', 'a'))
  2. s

Out[82]:

  1. {'a', 'b', 'c'}

In [83]:

  1. s.difference(('a', 'b'))

Out[83]:

  1. {'c'}

1.2.2.3. 赋值运算

Python类库参考:

赋值语句被用于(重)绑定名称与值,以及修改可变对象的项目或属性。

简单来说,它这样工作(简单赋值):

  • 右侧表达式被评估,创建或获得产生的对象

  • 左侧的名字被赋值或绑定到右侧的对象

需要注意的事情:

  • 单个对象可以有多个绑定的名称:

In [84]:

  1. a = [1, 2, 3]
  2. b = a
  3. a

Out[84]:

  1. [1, 2, 3]

In [85]:

  1. b

Out[85]:

  1. [1, 2, 3]

In [86]:

  1. a is b

Out[86]:

  1. True

In [87]:

  1. b[1] = 'hi!'
  2. a

Out[87]:

  1. [1, 'hi!', 3]
  • 要在原地改变列表,请使用索引或切片:

In [88]:

  1. a = [1, 2, 3]
  2. a

Out[88]:

  1. [1, 2, 3]

In [89]:

  1. a = ['a', 'b', 'c'] # 创建另一个对象
  2. a

Out[89]:

  1. ['a', 'b', 'c']

In [90]:

  1. id(a)

Out[90]:

  1. 4394695640

In [91]:

  1. a[:] = [1, 2, 3] # 在原地修改对象
  2. a

Out[91]:

  1. [1, 2, 3]

In [92]:

  1. id(a)

Out[92]:

  1. 4394695640

与上一个id相同,你的可能有所不同…

  • 这里的关键观点是可变 vs. 不可变

    • 可变对象可以在原地修改
    • 不可变对象一旦被创建就不可修改

更多内容在David M. Beazley的文章Python中的类型和对象中也可以找到关于以上问题非常不错的详尽解释。