python 迭代器与生成器

一、迭代器
对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration。(python内部对异常已处理)
class listiterator(object)
 |  Methods defined here:
 |  
 |  __getattribute__(...)
 |      x.__getattribute__('name') <==> x.name
 |  
 |  __iter__(...)
 |      x.__iter__() <==> iter(x)
 |  
 |  __length_hint__(...)
 |      Private method returning an estimate of len(list(it)).
 |  
 |  next(...)
 |      x.next() -> the next value, or raise StopIteration

listiterator
迭代:重复做一件事
iterable:可迭代对象
          支持每次返回自己所包含的一个成员对象
          对象实现了__iter__方法
          序列类型:list、str、tuple
          非序列类型:dict、file
          用户自定义包含了__iter__()或__getitem__()方法的类
li = [1,2,3,4,5,6,7]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mu__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']  
包含了__iter__
li.__iter__()
<listiterator object at 0x10ecf90>
返回了一个迭代器
也就说明了li是一个可迭代对象
>>> i1 = li.__iter__()
>>> i1.next()
1
>>> i1.next()
2
>>> i1.next()
3
>>> i1.next()
4
>>> i1.next()
5
>>> i1.next()
6
>>> i1.next()
7
>>> i1.next()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration
遍历完成后抛出异常,说明迭代结束,他不会从头在进行迭代
对象有迭代器的话我们就不需要手动再建立遍历
i2 = iter(li)
for循环可用于任何迭代对象

二、列表解析
    列表解析是python迭代机制的一种已用
    根据已有列表快速生成新列表的方式
>>> li = [1,2,3,4,5]
>>> 
>>> l1 = []
>>> for i in li:
...     l1.append(i**2)
...     
... 
>>> l1
[1, 4, 9, 16, 25]
列表解析语法
[ expression for iter_var in iterable ]

>>> l2 = [ i**2 for i in li ]
>>> l2
[1, 4, 9, 16, 25]
[ expression for iter_var in iterable if cond_expr ]
>>> l3 = [ i**2 for i in li if i >= 3 ]
>>> l3
[9, 16, 25]
可对于列表生成中直接应用列表解析器
这里就不用先生成一个1,10的列表
>>> for i in [ i**2 for i in range(11) ]:print i/2.0
... 
0.0
0.5
2.0
4.5
8.0
12.5
18.0
24.5
32.0
40.5
50.0
还可以更复杂应用
>>> for i in [ i**2 for i in range(11) if i %2 == 0]:print i/2.00
... 
0.0
2.0
8.0
18.0
32.0
50.0
举例:
取出/var/log/下面以.log结尾的文件
常规方法:
filelist = os.listdir('/var/log')
str.endswith('.log')
filelist2 = [ i for i in filelist   if i.endswith('.log') ] 
>>> filelist = os.listdir('/var/log')
>>> filelist2 = [ i for i in filelist   if i.endswith('.log') ] 
>>> filelist2
['gshell.log', 'mysqld.log', 'vmstart.log', 'repair.log', 'boot.log', 'ntp.log', 'dracut.log', 'yum.log', 'rdate.log']         

列表解析
filelist2 = [ i for i in  os.listdir('/var/log') if i.endswith('.log') ]

取出/etc目录下的是目录的文件
filelist3 = [ i for i in os.listdir('/etc') if os.path.isdir('/etc/%s' %i) ]
['depmod.d', 'rc4.d', 'audit', 'ld.so.conf.d', 'modprobe.d', 'backup', 'rc5.d', 'rc6.d', 'iproute2', 'bash_completion.d', 'security', 'yum', 'nginx', 'blkid', 'logrotate.d', 'rc0.d', 'ConsoleKit', 'lsb-release.d', 'statetab.d', 'rsyslog.d', 'sudoers.d', 'sasl2', 'ssl', 'pkcs11', 'redhat-lsb', 'skel', 'polkit-1', 'fonts', 'chkconfig.d', 'rc1.d', 'sysconfig', 'makedev.d', 'cron.monthly', 'udev', 'setuptool.d', 'lvm', 'rabbitmq', 'ssh', 'selinux', 'rpm', 'subversion', 'ppp', 'gtk-2.0', 'sensu', 'pango', 'cron.d', 'audisp', 'pcmcia', 'popt.d', 'dracut.conf.d', 'pam.d', 'alternatives', 'xinetd.d', 'rc3.d', 'NetworkManager', 'abrt', 'gnupg', 'dbus-1', 'terminfo', 'ntp', 'pki', 'hal', 'cron.daily', 'dhcp', 'yum.repos.d', 'init', 'plymouth', 'libreport', 'X11', 'pm', 'init.d', 'alsa', 'openldap', 'rc.d', 'rwtab.d', 'gcrypt', 'xdg', 'kdump-adv-conf', 'rc2.d', 'cron.weekly', 'postfix', 'scl', 'cron.hourly', 'opt','acpi', 'default', 'profile.d', 'prelink.conf.d', 'event.d', 'ansible'


三、生成器
生成器表达式并不真正创建数字列表,而是返回一个生成器对象,每次计算出一个条目后,把这个条目产生出来(yield)
使用了惰性计算或叫做延迟求值的机制
语法:
(exor for iter_var in iterable)
(exor for iter_var in iterable if cond_expr)
和列表解析区别在于小括号
是对列表解析的一种补充
range不是生成器 和 xrange 是生成器
类比列表解析和生成器
readlines不是生成器 和 xreadlines 是生成器
>>> print range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print xrange(10)
xrange(10)

(i**2 for i in range(11))这是一个对象
for i in (i**2 for i in range(11)):print i/2
生成器内部基于yield创建,即:对于生成器只有使用时才创建,从而不避免内存浪费

enumerate:
range可在非完备遍历中用于生成所以偏移,而非偏移处的元素
如果同时需要偏移索引和偏移元素,则可以使用enumerate()函数
此函数返回一个生成器对象
例如:返回文件行号和行值
>>> with open('/var/log/messages','r') as obj:
...     E = enumerate(obj)
...     for i in E:
...         print i 
...         
...     
... 
(0, 'Nov 15 03:22:01 iZ23tags5s2Z rsyslogd: [origin software="rsyslogd" swVersion="5.8.10" x-pid="813" x-info="http://www.rsyslog.com"] rsyslogd was HUPe
d\n')
(1, "Nov 15 13:14:24 iZ23tags5s2Z abrt: detected unhandled Python exception in '3.py'\n")
(2, 'Nov 15 13:23:34 iZ23tags5s2Z abrt: detected unhandled Python exception\n')
(3, 'Nov 16 00:37:05 iZ23tags5s2Z yum[22345]: Installed: pygobject2-2.20.0-5.el6.x86_64\n')
(4, 'Nov 16 00:37:06 iZ23tags5s2Z yum[22345]: Installed: python-pygments-1.1.1-1.el6.noarch\n')
(5, 'Nov 16 00:37:06 iZ23tags5s2Z yum[22345]: Installed: pycairo-1.8.6-2.1.el6.x86_64\n')
(6, 'Nov 16 00:37:07 iZ23tags5s2Z yum[22345]: Installed: pygtk2-2.16.0-3.el6.x86_64\n')
(7, 'Nov 16 00:37:07 iZ23tags5s2Z yum[22345]: Installed: bpython-0.9.7.1-3.el6.noarch\n')
有如下列表:
    [13, 22, 6, 99, 11] 
请按照一下规则计算:
13 和 22 比较,将大的值放在右侧,即:[13, 22, 6, 99, 11]
22 和 6 比较,将大的值放在右侧,即:[13, 6, 22, 99, 11]
22 和 99 比较,将大的值放在右侧,即:[13, 6, 22, 99, 11]
99 和 42 比较,将大的值放在右侧,即:[13, 6, 22, 11, 99,]
 
13 和 6 比较,将大的值放在右侧,即:[6, 13, 22, 11, 99,]
li = [13, 22, 6, 99, 11]
for i in range(1,5):    
    for m in range(len(li)-i): 
        if li[m] > li[m+1]:
            temp = li[m+1]
            li[m+1] = li[m]
            li[m] = temp



你可能感兴趣的:(python 迭代器与生成器)