1.list 列表 有序集合

classmates = ['Michael', 'Bob', 'Tracy']
len(classmates)
classmates[0]
len(classmates) - 1
classmates[-1]
classmates[-2]
classmates.append('Adam')
classmates.insert(1, 'Jack')
classmates.pop()
classmates.pop(1)
s = ['python', 'java', ['asp', 'php'], 'scheme']
s[2][1]

 

 

2.tuple 元组 是一个不可变的特殊list

一旦初始化后就不可以改变,它没有append(),insert()这样的方法
所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

t = (1, 2)
t = ()
t = (1,) #定义只有一个的tuple时候一定要注意在括号里面加上,号 为了和数学公式里面的小括号区分
t = ('a', 'b', ['A', 'B']) #特殊可变的tuple注意只是里面的list集合可以改变

 


3.dict 字典 使用键-值(key-value)存储,具有极快的查找速度

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
d['Adam'] = 67
'Thomas' in d
>>> d.get('Thomas') #注意:返回None的时候Python的交互环境不显示结果
>>> d.get('Thomas', -1)
-1

>>> d.pop('Bob') # 要删除一个key,用pop(key)方法,对应的value也会从dict中删除
75 

 

 

dict和list比较

dict有以下几个特点:

查找和插入的速度极快,不会随着key的增加而变慢;
需要占用大量的内存,内存浪费多。
而list相反:

查找和插入的时间随着元素的增加而增加;
占用空间小,浪费内存很少。
dict的key必须是不可变对象 python不可变类型为 数字、字符串、元组是不可变的,列表、字典是可变的


set 集合 set和dict类似,

也是一组key的集合,但不存储value。是一组无序无重复的数据结构
要创建一个set,需要提供一个list作为输入集合:
s = set([1, 2, 3])
s.add(4)
s.remove(4)
同样不可以放入可变对象

对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:

>>> a = ['c', 'b', 'a']
>>> a.sort()
>>> a
['a', 'b', 'c']

而对于不可变对象,比如str,对str进行操作呢:

>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'
于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。

tuple虽然是不变对象,但试试把(1, 2, 3)和(1, [2, 3])放入dict或set中,并解释结果。

list (可变)和 tuple(不可变)是有序可重复的数据结构
dict(可变) 和 set() 是无序不可重复的数据结构

>>> l = {1:1}
>>> l[2]= 2
>>> l
{1: 1, 2: 2}

切片
L[0:3]
L[:3]
L[-2:]
L[-2:-1]
L[:10:2]
L[::5]
(0, 1, 2, 3, 4, 5)[:3]
'ABCDEFG'[:3]

可迭代对象不一定要有下标 例如dict
dict 默认迭代的是k
for k, v in d.items()

使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行

>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代

Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
>>> for i, value in enumerate(['A', 'B', 'C']):
... print(i, value)
...
0 A

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)
...
1 1
2 4

列表生成器

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

>>> import os # 导入os模块,模块的概念后面讲到
>>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']

>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

 

生成器 generator

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

因为generator也是可迭代对象

>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

可以通过next()函数获得generator的下一个返回值
>>> next(g)
0
正确的方法是使用for循环,因为generator也是可迭代对象:

如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
要把fib函数变成generator,只需要把print(b)改为yield b就可以了
变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list、tuple、dict、set、str等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

迭代器 和 可迭代对象区别
Iterable Iterator
凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

for x in [1, 2, 3, 4, 5]:
pass