一、迭代器 对于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