切片

切片,Slice,听起来就像把吐司切成一片一片的,然后取出其中的几片或者连续的几片。对应到 Python 中,就相当于取出数组中特定的元素。

my_list = list(range(101))
slice0 = my_list[0:10]		#取出前十个0~9
slice1 = my_list[:10]		#同上
slice2 = my_list[0:10:2]	#对前十个,每2个取1一个
slice3 = my_list[-1:]		#取最后一个,100
slice4 = my_list[-2:]		#反向切片,从倒数第2个向后去 99,100

字符串也可以像上面那样操作。

string = 'hello'
string[0:2]		#'he'

迭代

判断是否为可迭代对象:

from collections import Iterable

isinstance(x, Iterable)

Python 可以对任何可迭代对象进行迭代,无论有无下标:

data = {
    'name': 'hanzo',
    'age': 38,
    'occupation': 'ninjia',
}

for key in data:
    print(data[key])
    
for value in data.values():
    print(value)
    
for key, value in data.items():
    print(key, value)

但是在迭代 list 的过程中,每一次迭代我们只能获得元素的值,而不能获得索引,使用 enumerate 函数可以解决:

my_list = ['hi', 1, True]

for value in my_list:
  print(value)
  
for index, value in enumerate(my_list):
  print(index, value)

列表生成式

列表生成式,List Comprehensions,即快速生成列表的表达式。

[x for x in range(11)]   #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[x + x for x in range(11)]	#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
[x for x in range(11) if x % 2 == 0]	#[0, 2, 4, 6, 8, 10]
[x + y for x in 'ABC' for y in 'XYZ']	#['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

生成器

生成器,Generator,即在使用过程中不断进行计算的结构,受使用驱动,节省内存。

比如,我们创建一个超长数组,但在实际应用中只会使用到前几个,这样后面的就太占用空间了,我们可以使用生成器,让数组的使用中不断地生长。

  • 简单声明

生成器的简单声明方式跟列表生成式类似,把[]改为()

generator = (x * x for x in range(11))
  • 详细声明

为了实现更复杂的逻辑,我们需要使用定义函数的方式来声明生成器,在产生元素的地方使用 yiedld 关键字即可(跟线程中的 yield 有点类似,相当于中断当前的动作,等到下次需要的时候再继续进行):

def fibonacci(max):		# Fibonacci 数列  1, 1, 2, 3, 5, 8, 13, 21, 34, ...
  n, a, b = 0, 0, 1
  while n < max:
    yield b
    a, b = b, a + b
    n = n + 1
  return 'finished'
  • 使用

可以使用 next(generator) 来获取生成器每一次产生的值,但可能会越界,直接使用 for 进行迭代较为合理:

generator = (x * x for x in range(11))
next(generator)		# 0
next(generator)		# 1
next(generator)		# 4
generator = (x * x for x in range(11))
for n in generator:
  print(n)

像上面的的 fibonacci 生成器的返回值直接用 for 遍历无法拿到,需要使用 next 来手动越界抛出 StopIteration 异常,返回值边包含在该异常中:

g = fibonacci(6)
while True:
  try:
    next(g)
  except StopIteration as e:
    print(e.value)
    break

迭代器

迭代器,Iterator,可以被 next 函数调用并不断返回下一个数值的对象。就像数据流,理论上可以只有源头而没有尽头,而且是惰性的。

注意区分 Iterable 和 Iterator,前者一般是可以用 for 循环进行遍历(数量是确定的),而 Iterator 对象一般是用 next 函数来产生下一个数值(数量不确定,并不知道后面还有多少个)。

像 list,tuple,dict 它们都是 Iterable 对象而不是 Iterator,生成器就比较厉害了,它既是 Iterable 又是 Iterator,不仅可以用 for 循环遍历,还可以用 next 来生成下一个数值。

list,tuple,dict 也可以转换成 Iterator:

from collections import Iterable, Iterator

my_list = ['hi', 1, True]
isinstance(my_list, Iterable)	#True
isinstance(my_list, Iterator)	#False

my_list_iter = iter(my_list)
isinstance(my_list_iter, Iterable)	#True
isinstance(my_list_iter, Iterator)	#True