python学习21之高级特性
一、 高级函数补充
1. zip
把两个可迭代的内容生成一个可迭代的tuple元素类型组成的内容
l1=[1,2,3,4,5]
l2=[11,22,33,44,55]
z=[i for i in zip(l1,l2)]
print(z) #[(1,
11), (2, 22), (3, 33), (4, 44), (5, 55)]
2. enumerate
对可迭代对象里每一个元素,配上一个索引,然后索引和内容构成tuple类型
em=enumerate(l2)
l3=[i for i in em]
print(l3) #[(0,
11), (1, 22), (2, 33), (3, 44), (4, 55)]
3. collections模块
(1) namedtuple
tuple类型,是一个可命名的tuple
import collections
Point=collections.namedtuple("Point",['x','y']) #创建一个元组类
p=Point(11,22) #实例化一个元组
print(p.x) #访问元组的x属性
print(p[0]) #按照元组下标法访问也可以
(2) deque
比较方便的解决了频繁删除插入带来的效率问题
q=collections.deque(['a','b','c'])
print(q)
q.append("d")
print(q)
q.appendleft("x")
print(q)
(3) defaultdict
当直接读取dict不存在的属性时,直接返回默认值
func=lambda:"12345678"
d1=collections.defaultdict(func)
d1["A"]=1
d1["B"]=2
print(d1["C"])
(4) counter
统计字符串中每个字符出现的次数
也可以进行词频统计
co=collections.Counter("AADHHANANV")
print(co)#Counter({'A': 4, 'H': 2, 'N': 2, 'D': 1, 'V': 1})
lst=["love","hello","love","hello","stu","tea"]
sc=collections.Counter(lst)
print(sc) #Counter({'love': 2, 'hello': 2, 'stu': 1, 'tea': 1})
二、 调试技术
分类:静态调试:
动态调试:
pdb调试
pycharm调试:run/debug模式
断点:程序在debug模式下遇到断点就会暂停运行
三、 列表高级操作
- 切片
- 迭代
#切片:取一个列表或者元组的部分元素
lst=["LY","I","LOVE","YOU"]
#取第一个元素---索引法,下标法
print(lst[0])
#切片操作
lst3=lst[0:3] #取前三个元素
print(lst3)
#从开头开始取,冒号(:)前面的数字0可以省略
lst3=lst[:3]
print(lst3)
#取到最后的话,冒号(:)后面的数字可以省略
#从第二个元素(下标是1)取到最后
lst4=lst[1:]
print(lst4)
#负数表示从后往前取
lstf1=lst[-1] #表示取倒数第一个元素
print(lstf1) #YOU
#每2个取一个,也就是取第1、3、5、7...个元素
lst2=lst[::2]
print(lst2)
如果给定一个list或tuple,我们可以通过while或for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)
3. 列表生成式
4. 生成器
#生成一个元素为1-10的列表
#法1;list函数
lst=list(range(1,11))
print(lst)
#法2:循环
lst=[i for i in range(1,11)]
print(lst)
#法3:循环2
lst=[]
for i in range(1,11):
lst.append(i)
print(lst)
#拓展:迭代字典的key 和 value
d={"xiaoming":100,"xiaoli":98,"xiaohong":95}
for k,v in d.items():
print(k,"的成绩是",v,"分")
#也可以用列表生成式实现上述功能
lst_dict=[k+"的成绩是"+str(v)+"分" for k,v in d.items()]
print(lst_dict)
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
#generator
#法1:将列表生成式的[]改为()
L=[x*x for x in range(10)]
print(L)#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g=(x*x for x in range(10))
print(g) #<generator object <genexpr> at 0x0000029937B04728>
#打印出generator的每一个元素 --->next函数
print(next(g)) #0
print(next(g)) #1
print(next(g)) #4
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
当然,上面这种不断调用next(g)存在不合理的地方,正确的方法是使用for循环,因为generator也是可迭代对象
for n in g:
print(n)
所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max):
n,a,b=0,0,1
while n<max:
print(b)
a,b=b,a+b
n=n+1
return 'done'
print(fib(6))
可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
要把fib函数变成generator,只需要把print(b)改为yield b就可以了。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n=n+1
return 'done'
print(fib(6)) #<generator object fib at 0x00000169FD5C47D8>
for i in fib(6):
print(i,end=' ') #1 1 2 3 5 8
generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行
5. 迭代器
可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
list、dict、str等数据类型不是Iterator。