>>> 1<2
True
>>> {1,2,} - {2,3}
{1}
>>> a = 1
>>> b = 2
>>> c = 0
>>> if a > b:
... c = a
... else:
... c = b
...
>>> c
2
# 上面等价于以下
>>> c = a if a > b else b # 等价于Java (a>b)?a:b
>>> c
2
2.1 列表解析即通过[]方括号括起来,表达式来创建列表, 如下代码
>>> l = []
>>> for x in range(10):
... l.append(x)
...
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
可以使用一句代码来完成创建
>>> ll = [x for x in range(10)]
>>> ll
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
通过三元表达式来抽取单数
>>> l = [x for x in range(1,11) if x%2 != 0]
>>> l
[1, 3, 5, 7, 9]
注:上述列表直接解析 在数据量不是很大的情况下 问题不大 但是如果涉及大量数据时 这个存在弊端 由于列表解析是一次性的读取并塞入内存中 存在内存不够使用的风险
此时可以通过迭代器来进行依次获取数据
通过列表解析,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表解析表达式的[]
改成(),就创建了一个generator:
>>> l = (x for x in range(100)) #此处不使用[] 使用() 代表生成的是一个生成器
>>> l
<generator object <genexpr> at 0x1057d37c8>
>>> next(l)
0
>>> next(l)
1
>>> for x in l:
... print(x,end=",")
...
2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,
如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> def test():
... yield 1
... yield 2
... yield 3
... yield 4
... yield 5
...
>>> test()
<generator object test at 0x1057d3840>
>>> for x in test():
... print(x)
...
1
2
3
4
5
# 变量生成器三种方式
>>> def yield_value(x):
... for i in range(x):
... name = yield i
... print("Name is:%s" % name)
...
# 用for循环 如上所示
>>> for x in yield_value(5):
... print(x)
...
0
Name is:None
1
Name is:None
2
Name is:None
3
Name is:None
4
Name is:None
# 生成迭代器,再next方法遍历
>>> yield_it = yield_value(5).__iter__()
>>> yield_it.__next__()
0
>>> yield_it.__next__()
Name is:None
1
>>> yield_it.__next__()
Name is:None
2
>>> yield_it.__next__()
Name is:None
3
>>> yield_it.__next__()
Name is:None
4
>>> yield_it.__next__()
Name is:None
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
# 使用send(value) 进行遍历
>>> yv = yield_value(5)
>>> yv.send(None)
0
>>> yv.send(None)
Name is:None
1
>>> yv.send("hello")
Name is:hello
2
>>> yv.send("world")
Name is:world
3
>>> yv.send(1)
Name is:1
4
>>> yv.send(1)
Name is:1
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
>>> yv.send(2)
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用==isinstance==()判断一个对象是否是**Iterable**对象:
>>> from collections import Iterable
>>> isinstance([],Iterable)
True
>>> test()
<generator object test at 0x1057d38b8>
>>> isinstance(test(),Iterable)
True
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
①凡是可作用于for循环的对象都是Iterable类型;
②凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
③集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
④Python的for循环本质上就是通过不断调用next()函数实现的
__iter__()
获取iterator
对象# 遍历可迭代对象的几种方式
# 方式一.
# 通过内置函数__iter__()获取iterator对象
>>> l = [1,2,3]
>>> iter_l = l.__iter__()
# 通过调用内置__next__()方法来获取值
>>> iter_l.__next__()
1
>>> iter_l.__next__()
2
>>> iter_l.__next__()
3
# 没有数据 提示抛出StopIteration异常
>>> iter_l.__next__()
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
iter(变量)
获取iterator
对象>>> l
[1, 2, 3]
>>> it_l = iter(l)
>>> it_l
<list_iterator object at 0x1058524e0>
>>> it_l.__next__()
1
>>> it_l.__next__()
2
>>> it_l.__next__()
3
>>> it_l.__next__()
Traceback (most recent call last):
File "" , line 1, in <module>
StopIteration
for
循环直接操作变量获取其iterator对象for循环直接会处理StopIteration异常
>>> l
[1, 2, 3]
>>> for x in l: # 此处l等价于 l.__iter__()
... print(x,end=" , ")
...
1 , 2 , 3
next(迭代器)
获取数据 or 迭代器.__next__()
获取数据>>> l
[1, 2, 3]
>>> a = iter(l)
>>> b = l.__iter__()
>>> next(a)
1
>>> next(a)
2
>>> next(a)
3
>>> b.__next__()
1
>>> b.__next__()
2
>>> b.__next__()
3
>>> def lbd(x,y):
... return x+y
...
>>> lbd(1,2)
3
# 与上述函数等价
# lambda 跟一个或多个形参 冒号后面跟 return的返回值
>>> x = lambda a,b:a+b
>>> x(1,2)
3
举例:l = [1,2,3,4,5,6,8,9] 对每个元素进行平方运算,常规方法如下
>>> l = [x for x in range(1,10)]
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> res_l = []
>>> for x in l:
... res_l.append(x**2)
...
>>> res_l
[1, 4, 9, 16, 25, 36, 49, 64, 81]
其好处在于,func参数传递的是一个函数。此时不管是灵活度也好,维护性也好。都非常?
如果需求变更为每个列表加2的话,直接修改squ函数即可。
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> def squ(x):
... return x**2
...
>>> def res(func,value):
... res = []
... for i in value:
... res.append(func(i))
... return res
...
>>> res(squ,l)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
对于上述需求直接可以通过map函数来简化代码
map函数的用法,map(函数名或lambda表达式,一个或多个可迭代对象)
map主要是争对可迭代对象中每个元素的操作,map返回的是可迭代对象
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> m = map(lambda x:x**2,l)
>>> m
<map object at 0x105857668>
>>> list(m)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
filter跟map的使用类似,功能上则是过滤可迭代对象中的元素
需求:l = [1,2,3,4,5,6,8,9] 筛选出3的倍数的数
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ft = filter(lambda x: x % 3 == 0,l)
>>> ft
<filter object at 0x1058576d8>
>>> list(ft)
[3, 6, 9]
reduce参数跟map、filter一样。reduce(函数名或lambda表达式,一个或多个可迭代对象,可选初始值)
功能上,reduce最终是聚合一个值
使用前需要导入该模块From functools import reduce
需求:l = [1,2,3,4,5,6,8,9] 求集合中每个元素相乘的乘积
>>> l
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> from functools import reduce
>>> res = reduce(lambda x,y:x*y,l)
>>> res
362880
>>> a = 1
>>> for x in l:
... a = a*x
...
>>> a
362880