龙空技术网

Python高级特性——为什么都说Python高效

SimpleAI 773

前言:

当前我们对“python 36新特性”都比较重视,朋友们都需要剖析一些“python 36新特性”的相关内容。那么小编也在网上搜集了一些关于“python 36新特性””的相关文章,希望同学们能喜欢,你们快快来了解一下吧!

本微教程根据廖雪峰python教程中的部分内容,配合我个人的学习经历进行总结整理。

分为以下四个部分:

神奇的切片——高效获取列表中想要的元素可迭代对象--列表、元组、字典等到底啥区别列表生成器--复杂的list,一行代码生成生成器/迭代器--generator、yield到底什么鬼1.神奇的切片

l = list(range(20))print(l)
>>输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
## 取出前3项,后3项,第6到第11项,倒数第2个到倒数第5个:first_3 = l[:3]last_3 = l[-3:]middle = l[5:11] # 指从l[5]到l[10],共11-5=6项last_2_5 = l[-5:-1] # 指从l[-5]到l[-2],共-1-(-5)=4项print("1:",first_3,"\n2:",last_3,"\n3:",middle,"\n4:",last_5_2)
>>输出:1: [0, 1, 2] 2: [17, 18, 19] 3: [5, 6, 7, 8, 9, 10] 4: [15, 16, 17, 18]
## 每1项、每2项、每3项取出一个:l_1 = l[::1]l_2 = l[::2]l_3 = l[::3]print("1:",l_1,"\n2:",l_2,"\n3:",l_3)## 分别取出奇数项、偶数项:l_odd = l[1::2] # 即,从第一项开始取,每两项取一个l_even = l[::2]print("---\nl的奇数项:\n",l_odd,"\nl的偶数项:\n",l_even)## 取出前10项中的奇数:l_first10_odd = l[1:10:2]print("\n前10项中的奇数:\n",l_first10_odd)
>>输出:1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 2: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 3: [0, 3, 6, 9, 12, 15, 18]---l的奇数项: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] l的偶数项: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]前10项中的奇数: [1, 3, 5, 7, 9]
2.可迭代对象

list、tuple、dict、string在python中都是可迭代对象,因此都可以用for来遍历。

l = [10,20,30,40]t = (10,20,30,40)d = {"a":1,"b":2,"c":3,"d":4,"e":5,"f":6}s = "Hello python!"for each in s:    print(each,end=' ')print()for each in d:    print(each,end=' ')print("\n注意到,直接打印dict的每一项,输出的只是【键】!")
>>输出:H e l l o   p y t h o n ! a b c d e f 注意到,直接打印dict的每一项,输出的只是【键】!
## 如果想单独获取dictionary的键或者值的列表,可以这样:items = list(d.items())keys = list(d.keys())values = list(d.values())print(items,"\n",keys,"\n",values)
>>输出:[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6)]  ['a', 'b', 'c', 'd', 'e', 'f']  [1, 2, 3, 4, 5, 6]
## 如果想获取可迭代对象每一项的序号,可以使用enumerate函数:for index,value in enumerate(l):    print(index," : ",value)
>>输出:0  :  101  :  202  :  303  :  40
3.一行代码生成列表——列表生成式基础版:对原list直接进行变换进阶版:添加一个条件if,甚至if…else…
l = list(range(10))print(l)
>>输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
## 生成l的每一项的平方的新列表:l_square = [x*x for x in l]print(l_square)
>>输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
## 在上面的基础上,加一个条件:要求元素大于30:l_square_above30 = [x*x for x in l if x*x>30]print(l_square_above30)
>>输出:[36, 49, 64, 81]
## 再玩一个更加复杂的,把l转换成:能被2整除的变为1,否则变为0:l_devideby2 = [1 if x%2==0 else 0 for x in l]print(l_devideby2)
>>输出:[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
"""练习:我们有一列名字,但是都没有首字母大写:names = ['david','adam','davis','bob','alice','judy','kate','djangh'].我们希望把首字母都大写,显示首字母是d的所有名字,其余的名字变为'---'."""names = ['david','adam','davis','bob','alice','judy','kate','djangh']selected = [name.capitalize() if name[0]=='d' else '---' for name in names]print(selected)
>>输出:['David', '---', 'Davis', '---', '---', '---', '---', 'Djangh']
4.生成器 generator

生成器是python的高级特性之一,我们经常听说这个词,但是一直都挺陌生的,而且平常写一写小型程序,做一些小项目,也许根本涉及不到这个玩意儿。所以,生成器存在的意义是什么?

一般情况下,我们存储一串数据,都是放在一个list里面,比方说,我们要读取一个文本,然后分词,把分词的结果放进一个list里面。如果文件很大的话,那相当于我们直接把这么大的一个东西存到了我们的内存中,这样会迅速加大计算机的负荷,影响我们的计算效率,甚至直接memory out了。

但是很多时候,我们并不是一次性就要使用所有数据,而是每次只用一小部分,那我们完全可以需要的时候,根据某种规则或者算法把要用的数据读进内存,用完就丢掉。这样,我们就不用创建完整的list,节省了内存。这种方法,我们称为生成器(generator)。

最简单创建一个generator的方法是,把列表生成器的[]改成():

simple_generator = (x for x in l)simple_generator
>>输出:<generator object <genexpr> at 0x000000DA987B65C8>
for i in simple_generator:    print(i,end=' ')## 或者可以调用next(generator)方法:    try:        next(simple_generator)    except StopIteration as e:        print("\n迭代器已经输出所有元素,不能继续迭代!")        print("Error info:",e.value)
>>输出:0 1 2 3 4 5 6 7 8 9 迭代器已经输出所有元素,不能继续迭代!Error info: None

另一种方法就是写一个函数,把想要迭代得到的值通过yield输出(本来输出是print,我们改成yield),这样,这个函数就变成了一个generator:

def fib(max):    n,a,b, = 0,0,1    while(n<max):                yield a        a,b = b,a+b        n += 1    return "Done!"
for i in fib(50):    print(i,end=' ')
>>输出:0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 4807526976 7778742049 
"""来一个难度更大一点的,输出杨辉三角形:          1         / \        1   1       / \ / \      1   2   1     / \ / \ / \    1   3   3   1   / \ / \ / \ / \  1   4   6   4   1 / \ / \ / \ / \ / \1   5   10  10  5   1要求得到一个generator,每次输出三角形的一行。"""# 方法1:# 根据规律,可以看出,第一行第二行分别是[1]和[1,1]# 到了第三行,把头尾的两个1去掉,中间的部分,就是由上一行去头与上一行去尾的和得到的# 因此可以写如下函数:def yanghui_triangle():    l = [1]    i = 0    while(True):                if len(l)==1:                        yield l            l = [1,1]                else:                        yield l            l = [x+y for x,y in zip(l[:-1],l[1:])]            l.insert(0,1)            l.append(1)
g = yanghui_triangle()print(g)
>>输出:<generator object yanghui_triangle at 0x00000085F970AFC0>
for i in range(10):    print(next(g))
>>输出:[1][1, 1][1, 2, 1][1, 3, 3, 1][1, 4, 6, 4, 1][1, 5, 10, 10, 5, 1][1, 6, 15, 20, 15, 6, 1][1, 7, 21, 35, 35, 21, 7, 1][1, 8, 28, 56, 70, 56, 28, 8, 1][1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
# 方法2:# 用最原始的规律,从三角形可以看出,每一项,都是上一行对应两项之和;# 但是直接用上一行的元素去相加,似乎少了点什么,# 这个时候我们发现,如果在每一行后面添加一个0,那么就可以解决这个问题:def yanghui_triangle2():    l = [1]        while(True):                yield l        l.append(0)  ## 增加一个长度        l = [l[i-1]+l[i] for i in range(len(l))]                ## l[-1]恰好是0,最后两项之和恰好是之前的最后一项
g2 = yanghui_triangle2()print(g2)
>>输出:<generator object yanghui_triangle2 at 0x00000085F9972BF8>
for i in range(10):    print(next(g2))
>>输出:[1][1, 1][1, 2, 1][1, 3, 3, 1][1, 4, 6, 4, 1][1, 5, 10, 10, 5, 1][1, 6, 15, 20, 15, 6, 1][1, 7, 21, 35, 35, 21, 7, 1][1, 8, 28, 56, 70, 56, 28, 8, 1][1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

总结:

从上面的四个部分,我们可以深刻感受到Python的简洁。

例如,我们通过列表生成式,可以把原本需要用for循环,再加上if...else...等等结构才能生成的一个列表,用一行代码就表示出来了,而且逻辑很清晰。

我们在实际编程的时候,应该尽可能多思考,如何利用Python的高级特性,让代码更简洁更高效。

标签: #python 36新特性