python之列表解析与生成器

简介:

  什么是列表解析?

    列表解析就是根据已有列表,高效生成新列表的方式

    列表解析是python迭代机制的一种应用,它常用于实现创建新的列表,因此要放置于[]中

  语法:

1
2
[expression  for  iter_var  in  iterable]
[expression  for  iter_var  in  iterable  if  cond_expr]

  例:

1
In [ 1 ]: L  =  [i * * 2  for  in  xrange ( 9 )]

1
2
In [ 2 ]:  print  L
[ 0 1 4 9 16 25 36 49 64 ]

  假设现在有一个列表list1,需要取得列表list1中每一个元素的平方,并生成一个新列表,可以这样做:

1
2
3
4
5
6
In [ 3 ]: list1  =  [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ]
 
In [ 4 ]: list2  =  [i * * 2  for  in  list1]
 
In [ 5 ]:  print  list2
[ 1 4 9 16 25 36 49 64 ]

  只把list1中元素值大于或等于3的计算机其平方,并生成新列表,可以这样做:

1
2
3
4
In [ 6 ]: list3  =  [i * * 2  for  in  list1  if  i > =  3 ]
 
In [ 7 ]:  print  list3
[ 9 16 25 36 49 64 ]

  列表解析能够使用比for循环快近一倍的方式基于已有的列表来生成新列表

  求1到10范围内10个数字的平方除以2的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
In [ 8 ]:  for  in  [i * * 2  for  in  xrange ( 1 , 11 )]:
    ...:      print  /  2
    ...: 
0
2
4
8
12
18
24
32
40
50

  返回1到10范围内所有偶数的平方除以2的结果:

1
2
3
4
5
6
7
8
In [ 9 ]:  for  in  [i * * 2  for  in  xrange ( 1 , 11 if  % 2  = =  0 ]:
    ...:          print  /  2
    ...: 
2
8
18
32
50

  把/root目录下所有以.log结尾的文件取出来,生成一个新列表:

1
2
3
4
5
6
In [ 10 ]:  import  os
 
In [ 11 ]: filelist  =  [i  for  in  os.listdir( "/root" if  i.endswith( ".log" )]
 
In [ 12 ]:  print  filelist
[ 'install.log' ]

  把/etc目录下所有目录取出来,生成一个新列表:

1
2
3
4
In [ 13 ]: directory1  =  [i  for  in  os.listdir( "/etc" if  os.path.isdir( "/etc/" + i)]
 
In [ 14 ]:  print  directory1
[ 'pkcs11' 'sasl2' 'xml' 'pear' 'terminfo' 'iscsi' 'sysconfig' 'security' 'statetab.d' 'NetworkManager' '.java' 'rc4.d' 'gcrypt' 'xinetd.d' 'ssh' 'httpd' 'dhcp' 'php.d' 'rc6.d' 'rpm' 'cron.daily' 'audit' 'selinux' 'depmod.d' 'dracut.conf.d' 'ntp' 'xdg' 'init' 'init.d' 'ConsoleKit' 'pm' 'yum' 'openldap' 'sudoers.d' 'logrotate.d' 'lxc' 'ppp' 'ld.so.conf.d' 'rwtab.d' 'dbus-1' 'gnupg' 'cron.weekly' 'sgml' 'pki' 'rc2.d' 'modprobe.d' 'audisp' 'exim' 'blkid' 'profile.d' 'cron.hourly' 'default' 'opt' 'rc0.d' 'ssl' 'fonts' 'sysctl.d' 'iproute2' 'X11' 'rc1.d' 'plymouth' 'rc.d' 'yum.repos.d' 'polkit-1' 'cron.monthly' 'pango' 'pam.d' 'rsyslog.d' 'prelink.conf.d' 'alternatives' 'rc3.d' 'makedev.d' 'popt.d' 'docker' 'udev' 'gconf' 'lvm' 'cgconfig.d' 'cron.d' 'chkconfig.d' 'bash_completion.d' 'skel' 'multipath' 'rc5.d' ]

  在使用列表解析时,for循环还可以嵌套for循环。举例说明:

  假设现在有两个列表list1和list2,现在要实现两个列表的元素交叉相乘,可以这样做:

1
2
3
4
5
6
7
8
In [ 15 ]: list1  =  [ 'x' , 'y' , 'z' ]
 
In [ 16 ]: list2  =  [ 1 , 2 , 3 ]
 
In [ 17 ]: list3  =  [(i,j)  for  in  list1  for  in  list2]
 
In [ 18 ]:  print  list3
[( 'x' 1 ), ( 'x' 2 ), ( 'x' 3 ), ( 'y' 1 ), ( 'y' 2 ), ( 'y' 3 ), ( 'z' 1 ), ( 'z' 2 ), ( 'z' 3 )]

  接下来实现当list2中元素值不为1时与list1交叉相乘,可以这样做:

1
2
3
4
In [ 19 ]: list4  =  [(i,j)  for  in  list1  for  in  list2  if  j ! =  1 ]
 
In [ 20 ]:  print  list4
[( 'x' 2 ), ( 'x' 3 ), ( 'y' 2 ), ( 'y' 3 ), ( 'z' 2 ), ( 'z' 3 )]


  列表解析会直接返回一个新列表,如果某个原列表里面的元素非常多,而列表解析又以几何倍数向上增长以后,就会极其占用内存,如此将导致效率低下。

  但是列表生成以后,一般一次只取一个元素,而for循环一次只遍历迭代其中的一个元素,基于此,使用直接生成一个列表的方式如此占用内存是极其不好的。

  由此我们可以对列表解析作一个扩展,就是把[]变成(),这就叫做生成器


  生成器和列表解析的关系就相当于xrange和range的关系,它可以让我们使用一个表达式,一次只生成计算出一个值,叫惰性计算方式。

  生成器不像列表解析一样,不管你用不用直接就生成了。生成器仅仅是你调用一次,它就可以返回一个,再调用一次,再返回一个。


  生成器表达式并不真正创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目“产生”(yield)出来.生成器表达式使用了“惰性计算”或称作“延迟求值”的机制

  当序列过长,并且每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析

  

  生成器特点:

    1、只有在调用时才会生成相对应的数据

    2、只记录当前位置,无法向前回溯,只能一步步往后走

    3、可以通过__next__()方法一次取一个值

    4、可以通过for循环取得所有值


  生成器表达式语法:

1
2
(expr  for  iter_var  in  iterable)
(expr  for  iter_var  in  iterable  if  cond_expr)

  

  生成器生成方法:

    1、通过列表解析进行生成

1
[ i * 2  for  in  range ( 10 ) ]

    2、通过函数生成(这里用著名的裴波那契数列来举例)

1
2
3
4
5
6
7
def  fib( max ):
     count,a,b  =  0 , 0 , 1
     while  count <  max :
         yield  b
         a,b  =  b,a + b
         count  + =  1
     return  'done'

  生成器的return返回值包含在异常当中,为避免程序抛出异常,仅通过捕捉异常的方式才能取得return返回值。

  yield保存了函数的中断状态。

  生成器是什么情况下会用到呢?这里通过一个例子来说明一下:

    生成器可以实现在单线程(串行)的情况下实现并发运算的效果

      生成器的__next__()方法只调用生成器的状态而不传值;

      生成器的send()方法在调用生成器的状态的同时给生成器传一个值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import  time
def  cut(cutter):
     print ( '%s 已经准备好撕纸了。' %  cutter)
     num  =  1
     while  True :
       paper  =  yield
       print ( '第%s张%s刚做好了,已经被%s撕了。' %  (num,paper,cutter))
      num  + =  1
def  make(maker):
     cutter1  =  cut( '撕纸员1' )
     cutter2  =  cut( '撕纸员2' )
     cutter1.__next__()
     cutter2.__next__()
     print ( '%s已经准备好做纸了。' %  maker)
     for  in  range ( 1 , 11 ):
         time.sleep( 1 )
         print ( '%s已经做好了1张纸' %  maker)
         cutter1.send(i)
         cutter2.send(i)
make( 'Tom' )

  返回1到10范围内所有正整数的平方:

1
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
In [ 21 ]: g1  =  (i * * 2  for  in  range ( 1 , 11 ))
 
In [ 22 ]: g1. next ()
Out[ 22 ]:  1
 
In [ 23 ]: g1. next ()
Out[ 23 ]:  4
 
In [ 24 ]: g1. next ()
Out[ 24 ]:  9
 
In [ 25 ]: g1. next ()
Out[ 25 ]:  16
 
In [ 26 ]: g1. next ()
Out[ 26 ]:  25
 
In [ 27 ]: g1. next ()
Out[ 27 ]:  36
 
In [ 28 ]: g1. next ()
Out[ 28 ]:  49
 
In [ 29 ]: g1. next ()
Out[ 29 ]:  64
 
In [ 30 ]: g1. next ()
Out[ 30 ]:  81
 
In [ 31 ]: g1. next ()
Out[ 31 ]:  100
 
In [ 32 ]: g1. next ()
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StopIteration                             Traceback (most recent call last)
<ipython - input - 32 - 9066a8f18086 in  <module>()
- - - - 1  g1. next ()
 
StopIteration:

  返回1到10范围内所有正整数的平方除以2的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
In [ 33 ]:  for  in  (i * * 2  for  in  range ( 1 , 11 )):
     ...:          print  /  2
     ...: 
0
2
4
8
12
18
24
32
40
50

  产生偏移和元素,使用enumerate函数:

    range可在非完备遍历中用于生成索引偏移,而非偏移处的元素

    如果同时需要偏移索引和偏移元素,则可以使用enumerate()函数,此内置函数返回一个生成器对象,例:

1
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
In [ 35 ]: url  =  'www.python.org'
 
In [ 36 ]: g2  =  enumerate (url)
 
In [ 37 ]: g2. next ()
Out[ 37 ]: ( 0 'w' )
 
In [ 38 ]: g2. next ()
Out[ 38 ]: ( 1 'w' )
 
In [ 39 ]: g2. next ()
Out[ 39 ]: ( 2 'w' )
 
In [ 40 ]: g2. next ()
Out[ 40 ]: ( 3 '.' )
 
In [ 41 ]: g2. next ()
Out[ 41 ]: ( 4 'p' )
 
In [ 42 ]: g2. next ()
Out[ 42 ]: ( 5 'y' )
 
In [ 43 ]: g2. next ()
Out[ 43 ]: ( 6 't' )
 
In [ 44 ]: g2. next ()
Out[ 44 ]: ( 7 'h' )
 
In [ 45 ]: g2. next ()
Out[ 45 ]: ( 8 'o' )
 
In [ 46 ]: g2. next ()
Out[ 46 ]: ( 9 'n' )
 
In [ 47 ]: g2. next ()
Out[ 47 ]: ( 10 '.' )
 
In [ 48 ]: g2. next ()
Out[ 48 ]: ( 11 'o' )
 
In [ 49 ]: g2. next ()
Out[ 49 ]: ( 12 'r' )
 
In [ 50 ]: g2. next ()
Out[ 50 ]: ( 13 'g' )
 
In [ 51 ]: g2. next ()
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StopIteration                             Traceback (most recent call last)
<ipython - input - 51 - 6d69cefe8ba3 in  <module>()
- - - - 1  g2. next ()
 
StopIteration:









本文转自 忘情OK  51CTO博客,原文链接:http://blog.51cto.com/itchentao/1883103,如需转载请自行联系原作者
目录
相关文章
|
9月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
490 2
|
9月前
|
开发者 Python
Python列表推导式:优雅与效率的完美结合
Python列表推导式:优雅与效率的完美结合
557 116
|
9月前
|
大数据 开发者 Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术
495 109
|
9月前
|
Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术
573 119
|
9月前
|
开发者 Python
Python列表推导式:优雅与效率的完美融合
Python列表推导式:优雅与效率的完美融合
416 104
|
9月前
|
Python
Python列表推导式:优雅与效率的艺术
Python列表推导式:优雅与效率的艺术
438 99
|
9月前
|
数据处理 Python
解锁Python列表推导式:优雅与效率的完美融合
解锁Python列表推导式:优雅与效率的完美融合
500 99
|
9月前
|
开发者 Python
Python列表推导式:一行代码的艺术与力量
Python列表推导式:一行代码的艺术与力量
589 95
|
10月前
|
开发者 Python
Python神技:用列表推导式让你的代码更优雅
Python神技:用列表推导式让你的代码更优雅
690 99
|
9月前
|
Python
Python列表推导式:简洁与高效的艺术
Python列表推导式:简洁与高效的艺术

热门文章

最新文章

推荐镜像

更多