仅为个人查阅使用,如有错误还请指正。
使用高级特性的原因就是为了代码能够简洁。代码越少,开发效率越高。
-
切片
列表和元组的切片操作完全相同。字符串也相差不多。
以列表为例
L = ["Harden", "Durant", "Jordan", "Curry", "O'Neal"] print(L[0:3]) # 取前3个元素 # output:['Harden', 'Durant', 'Jordan'] print(L[:3]) # 第一个索引是0,还可以省略 # output:['Harden', 'Durant', 'Jordan'] print(L[1:3]) # 从索引1开始,取出2个元素出来 # output:['Durant', 'Jordan'] print(L[:]) # L[:]实际上是复制,这种复制是浅拷贝。 # output:['Harden', 'Durant', 'Jordan', 'Curry', "O'Neal"] print(L[::2]) # 第三个参数表示每N个取一个 # output:['Harden', 'Jordan', "O'Neal"] # 倒序切片:记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。 print(L[-2:]) # 取最后两个元素 # output:['Curry', "O'Neal"] print(L[:-2]) # 删去最后两个元素 # output:['Harden', 'Durant', 'Jordan'] print(L[-3:-1]) # 从索引-3开始,取出两个元素 # output:['Jordan', 'Curry'] print(L[-4:-1:2]) # 从索引-4开始,每两个取一个,到索引-1前结束 # output:['Durant', 'Curry']
-
迭代
通过for循环来遍历字符串,列表,元组,字典等。遍历就相当于是迭代。
如果学过C语言或者Java语言都知道,迭代是通过下标来完成的。请看下面这个代码。
for (i=0; i<list.length; i++) { n = list[i]; }
而Python是通过
for...in...
来完成的。请看下面这个代码。for i in range(1, 100): if i % 7 == 0: print(i)
很明显,Python的迭代是取出元素本身,而非元素的索引。
如果想要在迭代的时候获取索引,可以通过
enumerate()
函数来获取。L = ["Harden", "Durant", "Jordan", "Curry", "O'Neal"] for index, name in enumerate(L): print(index, "--", name) # output: 0 -- Harden 1 -- Durant 2 -- Jordan 3 -- Curry 4 -- O'Neal
enumerate()
函数本质是把L变成了[(0, "Harden"), (1, "Durant"), (2, "Jordan"), (3, "Curry"), (4, "O'Neal")]
相当于是每个元素变成了元组。那也可以通过下标去访问。
注意:这个写法只是用来理解概念,推荐使用上面一种方法,因为方便简洁。
for i in enumerate(L): index = i[0] name = i[1] print(index, "--", name)
前面说了列表,元组,现在来说说一个比较特别的字典
注意:Python 3.6版本之前,字典是无序的,本环境是Python 3.6.5是有序的。
-
默认情况,字典遍历是内容是key
d = {"PF":"Jordan", "SF":"Durant", "C":"O'Neal", "SG":"Harden", "PG":"Curry"} for key in d: print(key) # output: PF SF C SG PG
-
如果需要遍历value,就使用
d.values()
。for value in d.values():
-
如果key,value都需要遍历,就使用
d.items()
for k, v in d.items()
如果判断一个对象是可迭代对象呢?需要通过
collections
模块的Iterable
类型判断。其实我觉得没有必要,把常用的记住就好了。稍微了解一下有这么一种方法就行。
from collections import Iterable print(isinstance("a", Iterable)) # 字符串是 print(isinstance([a, b, c], Iterable)) # 列表是 print(isinstance(123, Iterable)) # 整数不是
-
-
列表生成式
就是用一行代码实现一个列表,而且这个列表是可以灵活多变的。
-
生成列表
比如我们之前要生成一个列表,最傻瓜的办法就是自己创建一个。
稍微好一点的就用
list(range(1, 11))
,然后生成1到10这10个数字。或者稍微多变一点,
list(range(1, 10, 2))
,然后生成1到10的奇数。如果要添加一些运算,可能需要for循环来辅助。但是循环太繁琐。
这时我们可以使用Python特有的列表生成式来解决这个问题,而且是一行代码。
-
比如要生成[1×1,2×2, 3×3,...,10×10]
[x * x for x in range(1, 11)]
-
比如要生成[1×2,3×4, 5×6, 7×8,...,99×100]
[x * (x + 1) for x in range(1, 100, 2)]
-
-
条件过滤
顾名思义就是,可以在列表生成式里面加
if
语句。比如,把列表中的所有字符串变成小写,非字符串元素进行过滤
L = [35, "Durant", "Jordan", "Curry", "O'Neal"] print([name.lower() for name in L if isinstance(name, str)])
-
多层表达式
利用多层循环,找出对称的3位数,例如,101,121,232,222。
[x*100+y*10+z for x in range(1,10) for y in range(10) for z in range(10) if x == z]
-
-
生成器
前面提到了列表生成式,也明白列表容量会受到限制。占用太多的存储空间。
如果一个列表的元素可以通过某种算法推算出来,就可以节省很大空间,而这种机制就是生成器。
创建一个生成器,最简单的方法,就是用
()
来表示。例如g = (x * x for x in range(10)) print(g) # output:<generator object <genexpr> at 0x00000239CCD59C50> # 可以看到这是一个生成器,怎么去获取呢?使用next()函数,一个一个打印出来。 print(next(g)) # output:0 print(next(g)) # output:1 # 需要注意的是:生成器保存的是算法。 # 上面的next()方法是有点傻的,如果没有元素了,还会调用异常。所以一般都是用for循环去遍历的。 for n in g: print(n, end=",") # output:0,1,4,9,16,25,36,49,64,81,
前面说了,生成器是保存算法的,如果算法复杂,列表生成式的
for
循环无法实现,可以用函数来实现。以斐波那契数列来说,它的规则是除了第一个和第二个数外,任意一个数都由前两个数相加所得。
1,1,2,3,5,8,13,21,34,55,...
很显然,用列表生成式写不出来,但是,用函数可以很方便的实现。
def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'over' print(fib(6)) # output: 1 1 2 3 5 8 over
如上所述,这个
fib
函数实现了这个算法规则,整体的逻辑也符合生成器。但他始终是个函数。需要通过一个关键字yield,把函数变成生成器。这是另一种创建生成器的方法。
执行流程:第一次迭代,会执行到
yield b
,然后返回b的值,作为第一个迭代的返回值,那么第2次迭代,不会再去执行函数,而是从yield b
的下一条语句继续执行,直到再次遇到yield
。依此类推。def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'over' print(fib(6)) # <generator object fib at 0x000001494CE09A40> for n in fib(6): print(n)
总结:生成器可以用
[]
或者yield
,可迭代对象又多了一个(生成器) -
迭代器
前面在讲生成器的时候,有一个
next()
函数。迭代器的定义就是通过它来的。能够被next()函数调用,并不断返回下一个值的对象称为迭代器。
前面讲迭代的时候,讲到,如果要判断一个对象是否等着该对象,有一个
isinstance()
函数。迭代器的数据类型名称是:
Iterator
,迭代器相当于是一个数据流。from collections import Iterator print(isinstance((x for x in range(10)), Iterator)) # 生成器是 print(isinstance([1,2,3], Iterator)) # 列表不是 print(isinstance({"a":1, "b":2}, Iterator)) # 字典不是 print(isinstance('abc', Iterator)) # 字符串不是
有些同学可能会问,列表,字典,字符串都是可迭代对象,为什么不是迭代器。
这是因为迭代器表示的是一个数据流。因为它可以被
next()
函数调用并不断返回下一个数据。但是可以把可迭代对象变成迭代器,通过
iter()
函数。L = [1,2,3,4,5] a = iter(L) print(next(a)) # output:1 print(next(a)) # output:2 print(next(a)) # output:3
总结:迭代器的两个基本方法
iter()
,next()
。