迭代器和解析

迭代器

迭代工具:for, 列表解析,in成员关系测试,map内置函数等。

可迭代对象:可以在迭代工具环境中(例如,for)一次产生一个结果的对象,就可以看做是可迭代的。

 

可迭代的:支持iter的一个对象

迭代器:iter所返回的一个支持next(I)的对象

迭代协议:有__next__方法的对象会前进到下一个结果,而在一系列结果的末尾时,则会引发StopIteration。在Python中,任何这类对象都认为是可迭代的。任何这类对象也能以for循环或其他迭代工具遍历,因为所有迭代工具内部工作起来都是在每次迭代中调用__next__,并且捕捉StopIteration异常来确定何时离开。

 

文件迭代器:

for line in open('script.py'):    #use file iterators to read by lines
    print(line.upper(), end=' ')    #Calls __next__, catches StopIteration

上例是读取文本文件的最佳放啊,原因有三:这是最简单的写法,运行最快,并且从内测使用情况来说也是最好的

for i in open(xxx).readlines方法将文件内容加载到内存,会占用很多内存,如果文件很大,计算机内存空间不够,甚至不能工作。

比起迭代器for循环,while运行更慢,因为迭代器在python中以C语言的速度运行的,而while则是通过python虚拟机运行python字节码的。

 

手动迭代:iter and next

python 提供一个内置函数next,它会自动调用一个对象的__next__方法。

f = open('script.py')
next(f)

文件对象就是自己的迭代器,列表以及很多其他的内置对象,不是自身的迭代器,因为它们支持多次打开迭代器。对这样的对象,我们必须调用iter来启动迭代:

>>> l1
[1, 2, 3, 4]
>>> iter(l1)is l1    #列表不是自身的迭代器
False
>>> l1.__next__()    #列表没有__next__方法
Traceback (most recent call last):
  File "<pyshell#71>", line 1, in <module>
    l1.__next__()
AttributeError: 'list' object has no attribute '__next__'
>>> I = iter(l1)    #调用iter启动迭代
>>> I.__next__()
1
>>> next(I)    # important; next(I) same as I.__next__
2
>>> I.next()    # attention, this is not support
Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    I.next()
AttributeError: 'list_iterator' object has no attribute 'next'
>>> for x in l1:     # automation iteration
        print(x, end=' ')    # obtains iter, calls __next__, catches exceptions

1 2 3 4 
>>> I = iter(l1)    # manual iteration
>>> while True:
	try:                   # try statement catches exceptions
		x = next(I)    # or calls I.__next__()
	except StopIteration:
		break
	print(x**2, end=' ')

	
1 4 9 16 

列表解析:初探

[x**2 for x in L]
[line.strip() for line in open(xxx) if line[0] == 'p']
[x+y for x in 'abc' for y in 'xyz']

列表解析并不完全和for循环语句版本相同,因为它会产生一个新的列表对象。列表解析会比手动的for循环语句运行的更快(往往快一倍),因为他们的迭代在解释器内部以C语言的速度执行的,而不是以手动python代码执行的,特别是对于较大的数据集合,这是使用列表解析的一个主要的性能优点。

其他迭代环境

列表解析、in成员关系测试、map内置函数以及像sorted和zip调用这样的内置函数也都使用了迭代协议。

map类似于列表解析,但是它更有局限性,因为它需要一个函数而不是一个任意的表达式。

sorted排序可迭代对象中的各项,zip组合可迭代对象中的各项,enumerate根据相对位置来配对可迭代对象的项,filter选择一个函数为真的项,reduce针对可迭代对象中的成对的项运行一个函数。所有这些都接受一个可迭代的对象。Python3中,zip, enumerate和filter也像map一样返回一个可迭代对象。

>>> sorted(open('threenames.py'))
["a = 'dude'\n", "b = 'parrot'\n", "c = 'sketch'\n", 'print(a,b,c)\n']

>>> map(str.upper,open('threenames.py'))
<map object at 0x000001C1649BE588>
>>> list(map(str.upper,open('threenames.py')))
["A = 'DUDE'\n", "B = 'PARROT'\n", "C = 'SKETCH'\n", 'PRINT(A,B,C)\n']

>>> 'aaa' in open('threenames.py')
False
>>> 'sketch' in open('threenames.py')
False
>>> "c = 'sketch'\n" in open('threenames.py')
True

>>> list(zip(open('threenames.py'),open('threenames.py')))
[("a = 'dude'\n", "a = 'dude'\n"), ("b = 'parrot'\n", "b = 'parrot'\n"), ("c = 'sketch'\n", "c = 'sketch'\n"), ('print(a,b,c)\n', 'print(a,b,c)\n')]
>>> list(enumerate(open('threenames.py')))
[(0, "a = 'dude'\n"), (1, "b = 'parrot'\n"), (2, "c = 'sketch'\n"), (3, 'print(a,b,c)\n')]

>>> list(filter(bool,open('threenames.py')))
["a = 'dude'\n", "b = 'parrot'\n", "c = 'sketch'\n", 'print(a,b,c)\n']

>>> import functools, operator
>>> functools.reduce(operator.add, open('threenames.py'))
"a = 'dude'\nb = 'parrot'\nc = 'sketch'\nprint(a,b,c)\n"
>>> 

如下示例中的所有根据接受任何可迭代对象作为一个参数,并且使用迭代协议来扫描它,但返回单个的结果:

>>> l1
[1, 2, 3, 4]
>>> sum(l1)
10
>>> max(l1)
4
>>> min(l1)
1
>>> l2 = ['spam','','ni']
>>> any(l2)
True
>>> all(l2)
False

集合解析,字典解析

l1 = [1,2,3,3]
{x for x in l1}
{ix: x for ix, x in enumerate(l1)}
{x for x in l1 if x > 1}
{ix: x for ix, x in enumerate(l1) if x == 3}

其他迭代器主题:(后面介绍)

使用yield语句,用户定义的函数可以转换为可迭代的生成器函数

当编写圆括号的时候,列表解析转变为可迭代的生成器表达式

用户定义的类通过__iter__或__getitem__运算符重载变得可迭代

 

Learning Python, Fourth Edition, by Mark Lutz.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中的迭代器和列表解析都是用于处理序列数据的工具,但它们的实现方式和用途有所不同。 迭代器是一个可以遍历序列数据的对象,它提供了__next__()方法来获取序列中的下一个元素,如果序列已经遍历完了,则会抛出StopIteration异常。迭代器可以用于处理大型的序列数据,因为它不需要一次性将所有数据放进内存中,而是逐个获取需要的元素。以下是一个简单的迭代器示例: ```python class MyIterator: def __init__(self, data): self.index = 0 self.data = data def __iter__(self): return self def __next__(self): if self.index >= len(self.data): raise StopIteration result = self.data[self.index] self.index += 1 return result # 使用迭代器遍历列表 my_list = [1, 2, 3] my_iterator = MyIterator(my_list) for item in my_iterator: print(item) ``` 列表解析是一种简洁的语法,用于快速生成新的列表。它使用类似于for循环的语法来遍历原始列表,并使用条件表达式来过滤和转换列表中的元素。以下是一个简单的列表解析示例: ```python # 使用列表解析生成新的列表 my_list = [1, 2, 3] new_list = [x**2 for x in my_list if x > 1] print(new_list) # 输出 [4, 9] ``` 在上面的代码中,我们使用列表解析遍历原始列表my_list,并使用条件表达式过滤出大于1的元素,并将它们的平方放入新的列表new_list中。列表解析更适合用于简单的转换和过滤操作,而不是复杂的迭代操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值