list and tuple and string数据操作
1. 切片语法
list = list(range(100))
result = []
for i in range(3):
result.append(list[i])
等价于
result = list[0:3] # 这个就是切片语法,表示从索引0开始直到索引3而不包含3,就是取 0,1,2
如果从0位置开始索引可以省略为:
result = list[:3]
>>> [0,1,2]
类似的,Python支持取倒数第一个元素,那么它同样支持倒数切片:
result = list[-2:] # 表示从倒数第二个元素到最后一个元素。最后一个元素的index = -1
>>> [98,99]
list[::5] # 所有数,每5个取一个
>>> [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
list[:10:2] # 前10个数,每两个取一个:
>>> [0, 2, 4, 6, 8]
总结:tuple也是一种list,字符串'xxx'也可以看成是一种list,都支持切片语法 (substring)
2. 迭代
# 判断一个数据能不能被迭代
from collections import Iterable
isinstance("abc",Iterable) # 判断字符串是否可以迭代
isinstance(["a","b"],Iterable) # 判断list是否可以迭代
isinstance({"a":"b"},Iterable) # 判断dict是否可以迭代
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
# 默认是对key迭代的
for value in d.values()
# 对value迭代
for k,v in d.items()
# 对key and value迭代
// Python内置的enumerate函数可以把一个list变成索引-元素对
for index,value in enumerate(['A', 'B', 'C']):
# 迭代索引和元素本身
# 迭代多个变量
>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)
...
1 1
2 4
3 9
3. 列表生成式
list = list(range(1,11))
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
L = []
for i in range(1,11):
L.append(i**2)
>>> L # [1x1, 2x2, 3x3, ..., 10x10]
上面用列表生成式实现:
>>> L = [x**2 for x in range(1,11)]
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
还可以加判断:
>>> L = [x**2 for x in range(1,11) if x %2 == 0]
>>> L
[4, 16, 36, 64, 100]
还可以使用两层循环,可以生成全排列:
>>> L = [m+n for m in 'ABC' for n in 'XYZ']
>>> L
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
三层和三层以上的循环就很少用到了:
L = [x + y+ z for x in '123' for y in 'abc' for z in 'xyz']
>>> L = [x + y+ z for x in '123' for y in 'abc' for z in 'xyz']
>>> L
['1ax', '1ay', '1az', '1bx', '1by', '1bz', '1cx', '1cy', '1cz', '2ax', '2ay', '2az', '2bx', '2by', '2bz', '2cx', '2cy', '2cz', '3ax', '3ay', '3az', '3bx', '3by', '3bz', '3cx', '3cy', '3cz']
应用:
1. 运用列表生成式,列出当前目录下的所有文件和目录名:
>>> 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']
2. 把一个list中所有的字符串变成小写:
>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
继续延展:列表生成是基于for的(个人理解,可能不对!!!!),因为for 可以 for k,v in dict.items()
>>> d = {'x':'a','y' : 'b','z':'c'}
>>> d
{'x': 'a', 'y': 'b', 'z': 'c'}
>>> L = [k + '=' + v for k,v in d.items()]
>>> L
['x=a', 'y=b', 'z=c']
>>>
追加说明:列表生成式中的 if else使用
>>> L = [x**2 for x in range(1,11) if x %2 == 0]
>>> L
[4, 16, 36, 64, 100]
>>> L = [x**2 if x %2 == 0 else -x for x in range(1,11)]
>>> L
[-1, 4, -3, 16, -5, 36, -7, 64, -9, 100]
>>>
# 总结:在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else。if成立则返回x**2 不成立则返回-x!
# 测试:文字叙述下面2个L2啥意思
L1 = [123,'aaa','swr',None]
L2 = [s.lower() for s in L1 if isinstance(s,str)]
L2 = [s.lower() if isinstance(s,str) else s for s in L1]
答案:
第一个先把字符串筛选出来然后变小写然后输出。
第二个迭代的时候判断是字符串则变小写,不是则不作处理输出。
4. generator(生成器):一边循环一边计算的机制,称为生成器,遇到yield就中断,下次又继续执行!,定义generator的一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
# 生成式生成一个最简单的生成器
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630> # 生成器没法和数组一样全部罗列出来,因为一边循环一边计算的机制
# 访问生成器元素:每次调用next(g),就计算出g的下一个元素的值.
next(g)
# generator也是可迭代对象,因此可迭代
>>> g = (x * x for x in range(10))
>>> for n in g:
# 迭代器应用:
// 斐波拉契数实现:
def fib(max):
n,a,b = 0,0,1
while n < max:
print(b)
a,b = b,a+b
n = n+1
return "done"
说明:
a,b = b,a+b # 等价于下面
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
// 用迭代器改写: yield是迭代器的关键字
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
// 上面说了迭代器是可迭代的对象。因此
>>> for n in fib(6):
... print(n)
>>>
... 1
...
... 8
发现没有打印'done'
// 如果想要拿到返回值,必须捕获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
5. 迭代器:
/* 世界观:
直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
其中generator(生成器)不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值。
可以被next()函数调用并不断返回下一个值的“对象”称为迭代器:Iterator
*/
# isinstance()判断一个对象是否是Iterator对象也可以使用isinstance()判断一个对象是否是Iterable对象
>>> from collections.abc import Iterable
isinstance([], Iterable) # Iterable对象是list类型
>>> True
isinstance((x for x in range(10)), Iterator) # (x for x in range(10)) 这个是个生成器对象,判断他是不是Iterator类型
>>> True
小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass
实际上完全等价于:
it = iter([1, 2, 3, 4, 5])
while True:
try:
x = next(it) # 获得下一个值:
except StopIteration:
break # 遇到StopIteration就退出循环
网友评论