Python 列表生成式:
x从range里面取元素,然后对x进行运算,生成列表
list1 = [x for x in range(10)] #列表生成式 print(list1) #执行结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
或者可以这样:
list1 = [x**2 for x in range(10)] #列表生成式 print(list1) #执行结果: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
运算符可以是函数:
def f(x): return x**3 list1 = [f(x) for x in range(10)] #列表生成式 print(list1) #执行结果: [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
def f(x): return x**3 list1 = [f(x) for x in range(10)] #列表生成式 print(list1) print(type(list1)) #执行结果: [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] <class 'list'>
另一种赋值形式:要求一一对应,不然就报错。
t = (123,"abc") a,b = t print(a) print(b) #执行结果: 123 abc
t = [123,"abc",891] #可以是列表 a,b,c = t print(a) print(b) print(c) #执行结果: 123 abc 891
Python 生成器:一边循环,一边计算的机制,叫作生成器
内存的效率
生成器就是一个可迭代对象!!!
生成器创建方式:
1.0 小括号的方式(s = (x*2 for x in range(10)))
2.0 yield创建
s = (x*2 for x in range(10)) print(s) #执行结果: <generator object <genexpr> at 0x0000000001EB6138>
调用方法:next()
s = (x*2 for x in range(10)) print(next(s)) print(next(s)) print(next(s)) print(next(s)) #执行结果: 0 2 4 6
相当于:__next__()
s = (x*2 for x in range(10)) print(s.__next__()) print(s.__next__()) print(s.__next__()) print(s.__next__()) #执行结果: 0 2 4 6
超出了就会报错:StopIteration
用for循环来遍历一次:
s = (x*2 for x in range(10)) for i in s: print(i) #执行结果: 0 2 4 6 8 10 12 14 16 18
生成器函数:
def generator_function(): yield
在一个一般函数中使用yield关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield与return返回相同的值,区别在于return返回后,函数状态终止,而yield会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
看看yield与return的区别:
def generator_function1(): print("ok") return 100 generator_function1() def generator_function(): print("ok") yield 100
generator_function()
#执行结果:
ok
空
def generator_function(): print("ok") yield 100 t = generator_function() print(t) #执行结果: <generator object generator_function at 0x00000000021F6138>
所以yield函数就是一个生成器对象。
def generator_function(): print("ok") yield 100 print("ok22") yield 99 t = generator_function() print(t) next(t) #保留在yield 100 next(t) #第二次从yied 100以下开始走。不是从开头走 #执行结果: <generator object generator_function at 0x0000000002216138> ok ok22
也可以用for:
def generator_function(): print("ok") yield 100 print("ok22") yield 99 for i in generator_function(): print(i) #执行结果: ok 100 ok22 99
斐波那契数列
def fibo(max): n,before,after = 0,0,1
print(n) while n < max: print(after) before,after = after, before + after n = n + 1 fibo(10) #执行结果: 0 1 1 2 3 5 8 13 21 34 55
用生成器来改:
def fibo(max): n,before,after = 0,0,1 while n < max: # print(after) yield before before,after = after, before + after n = n + 1 g = fibo(8) print(g) print(next(g)) #执行结果
<generator object fibo at 0x0000000002216138> 0
yield()还有一个send()方法:
send():可以传值,第一次进函数只能传None,等同于next(b)
def battle(): print("battle one") count = yield 1 print(count) print("battle two") yield 2 print("battle three") yield 3 b = battle() b.send(None) #可以传值,第一次进函数只能传None,等同于next(b) b.send(99)
for 循环语句,深入理解:
1.0 for循环后面加的是可迭代对象。
可迭代对象:内部有用iter()方法的对象都是可迭代对象。列表,元组,字典都是可迭代对象
2.0 内部调用了next方法。
生成器函数包含一个或者多个yield当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代一旦函数被yield,函数会暂停,控制权返回调用者局部变量和它们的状态会被保存,直到下一次调用函数终止的时候,StopIteraion会被自动抛出生成器如何节省资源?
只记住当前位置,生成器只保留一个值,next之后上一个值就没有了
只有一个next方法
生成器都是迭代器,迭代器不一定是生成器!!!