第一招:生成式
第一类:列表生成式
场景:将a列表中的所有元素放到另一个list里面
我们使用for循环会写成下面的代码
a = range(1,10)
b = []
for i in a:
b.append(i)
print(b)但是,python这么优雅的语言,允许我们使用列表生成式进行数据拷贝,数据过滤(相当于filter),实现相同的功能,列表生成式只需要一行
b=[i for i in a]
咱们看下远行结果:结果相同,代码量还少了,不错吧~
另外列表生成式还支持筛选,比如我们1到9之间的所有偶数
比较简洁吧,这种适合条件筛选和python的内置函数filter(过滤器)差不多,后面咱们说fiilter
第二类:字典生成式,和列表生成式的写法类似,它是下面的形式:
s = { 'i'+str(i):i for i in c } # c是上面的偶数列表
还可以使用将value设置成set(),list()用于一些数据制作非常有用,比如我们将要搜集各个省有哪些学校,我们已经有了省和对应学校的数据,但是学校在处理过程中重复出现,我们需要重新建立一个像是:省份:set(学校1,学校2,,,),这样的结构,我们可以将原来:省份:list[学校1,学校2,,,]写成下面的字典生成式:
pro_sh= { province:set(raw_schools) for province,raw_schools in pro_shools.iteritems()}完成对原始字典的数据去重工作,在此去重列表可以直接使用set(),对list进行set(lst)获取一个set()集合,但是set不能进行下标操作,因此如果想要用下标,再讲set转回到list即可
2.第二招:生成器
什么是生成器,Python的生成器就是一个参数为可迭代对象的迭代函数,对应yield关键字。为啥用生成器,因为生成器可以节省内存?减少不必要的列表展开消耗,比如我们遍历一个列表
for i in a:
print i可以这样很简单,当时它在迭代遍历的时候相当于
for i in [1,2,3,4,5,6]:
print i这样对于循环过程的迭代会带来不小的问题,我们尝试使用生成器:
def generator(iterable_obj):
for i in iterable_obj:
print("before")
yield i
print("after")
for i in generator(a):
print i有啥不一样?生成器一次返回一个迭代对象,for用这一个对象去运行本次循环开销小了啊!
对于dict对象的遍历可以写运用items方法
def dict_generator(iterable_obj):
for k,v in iterable_obj.items():
print("before")
yield k,v
print("after")3.第三招:map-reduce函数:分治,合并
map函数主要用于对list这种对象进行每个元素都就像相同的处理;
reduce函数用于将list元素进行合并;
比如我解析100个相同格式的xml,将所有xml文件中的item节点合成一个所有的列表,并返回一个list
首先,我们看一下file1的xml的格式;
<DOCUMENT>
<item>a</item>
<item>b</item>
<item>c</item>
,,,
</DOCUMENT>
我们将解析xml到xmldom的过程处理作成一个函数
def read_parse(xmlfile_name):
sobj = None
with open(xmlfile_name,"r") as f:
sxml = f.read()
sobj etree.XML(sxml,etree.XMLParser())
return sobj然后我们假设有100个xml文件,文件名为test_i.xml i={1,100}
我们接着进行处理,拿到所有的文件名
file_names = [ "test_{_i}".format(_i=i) for i in range(1,101)]接着我们对所有文件解析,并构建xml
xml_doms = map(lambda x:read_parse(x),file_names)上面代码相当于
xml_doms = []
for i in file_names:
xml_doms.append(read_parse(i))考虑xml有可能解析失败返回None,我们需要使用filter进行None的过滤
xml_doms = filter(lambda x:x!=None,xml_doms)过滤完之后,我们需要从各个xml_dom中获取所有item子节点,有如下代码
xml_doms = map(lambda x:x.findall(".//item"),xml_doms)上面的lambda x:x.findall会将xml下面的所有item节点找到并返回一个list,因此上面代码会生成一个二维list,第一维是文件标号,第二维是那个文件中所有item节点
[[],[],[],[],...]接着我们使用reduce合并所有列表
xml_doms = reduce(xml_doms,lambda x,y:x+y)之所以可以这么干是因为list支持+操作,比如
所以合并list,不只是有extend方法,还有+号方法
这样我们将100个xml中的所有item节点都拿到了
最后,我们回顾一下哪三招?
生成式:列表生成式,字段生成式
生成器:可中途返回的参数为可迭代对象的可迭代函数
map-reduce:相同处理,归一合并
你get到了吗?