python iterator iterable_Python之Iterable与Iterator

1.Iterable与Iterator介绍

(1)iterable:具体应该叫做可迭代对象。他的特点其实就是我的序列的大小长度已经确定了(list,tuple,dict,string等)。他遵循可迭代的协议。

可迭代协议:含__iter__()方法。且可迭代对象中的__iter__()方法返回的是一个对应的迭代器。(如list对应的迭代器就是list_iterator)

(2)iterator:具体应该叫做迭代器的对象。他的特点就是他不知道要执行多少次,所以可以理解不知道有多少个元素,每调用一次__next__()方法,就会往下走一步,当然是用__next__()方法只能往下走,不会回退。是惰性的。这样我可以存很大很大的数据,即使是整个自然数,也可以很轻松的用迭代器来表示出来。他满足的是迭代器协议。

迭代器协议:含__iter__()方法。且方法返回的Iterator对象本身

含__next__()方法,每当__next__()方法被调用,返回下一个值,直到没有值可以访问,这个时候会抛出stopinteration的异常。

2.iterable与Iterator的关系

我们从上面的介绍可以看出。通俗的将就是类中如果满足可迭代的协议也就是有__iter__()的时候就可以成为可迭代对象。同理如果一个类中有__iter__()和__next__()方法的时候也就可以称之为迭代器。那他们两个到底什么关系呢?

>>> from collections import Iterator, Iterable

>>> help(Iterator)

Help on class Iterator:

class Iterator(Iterable)

| Method resolution order:

| Iterator

| Iterable

| builtins.object

|**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。

| Methods defined here:

|

| __iter__(self)

|

| __next__(self)

| Return the next item from the iterator. When exhausted, raise StopIteration

......

>>> help(Iterable)

Help on class Iterable:

class Iterable(builtins.object)

| Methods defined here:

|

| __iter__(self)

......

从上面的代码我们很清楚的看出Iterator继承iterable。这样我们就很清楚的看到了他们之间的关系了。

那我们说能不能把iterable转换Iterator呢?当然可以。可以通过iter()函数进行转换。其实说白了执行iter()方法就是去调用类中的__iter__()方法。其实前面也说了对于iterable如果执行了__iter__()方法他返回的是对应的itertor对象。如果Iterator调用__iter__()方法他返回的就是他自己(也就是一个迭代器)。iter(iterable)-->iterator

iter(iterator)-->iterator

那我们看看下面这段代码:

list = [1,2,3,4]

list_iterator = iter(list)

list.__next__()

Traceback (most recent call last):

File "G:/Python源码/iterable_test.py", line 3, in

list.__next__()

AttributeError: 'list' object has no attribute '__next__'

print(type(list))

print(type(list_iterator))

我们的list是一个可迭代的对象。可以调用iter(list)说明我们的list中肯定有__iter__()方法。

list_iterator = iter(list)

list的源码中找到了这个方法。

def __iter__(self, *args, **kwargs): # real signature unknown

""" Implement iter(self). """

pass

从下面这段报错代码中我们可以看出,list中一定是没有__next__()方法的。

list.__next__()

Traceback (most recent call last):

File "G:/Python源码/iterable_test.py", line 3, in

list.__next__()

其实for循环中对于iterable对象有一个转换。

for x in [1,2,3,4,5]:

pass

等价于===>

#先获取iterator对象

it = iter([1,2,3,4,5])

while True:

try:

#获取下一个值

x = next(it);

except StopIteration:

# 遇到StopIteration就退出循环

break

3.如何去判断Iterator和iterable

可以使用isinstance()判断一个对象是否是Iterable,Iterator对象:

from collections import Iterable,Iterator

list = [1,2,3,4]

list_iterator = iter(list)

print(isinstance(list,Iterable),isinstance(list,Iterator))#True False

print(isinstance(list_iterator,Iterable),isinstance(list_iterator,Iterator))#True True

从上面我们也可以看出。迭代器(iterator)一定是可迭代对象,但是可迭代对象(iterable)不一定。

4.如何自定义一个迭代器

class EvenIterators(object):

def __init__(self,n):

self.stop = n

self.value = -2

#实现__iter__()方法并返回自身(因为迭代器[实现__iter__和__next__])

def __iter__(self):

return self

def __next__(self):

if self.value+2 > self.stop:

raise StopIteration

self.value += 2

return self.value

e = EvenIterators(10)

print(e.__next__())

print(e.__next__())

print(e.__next__())

print(e.__next__())

for en in e:

print(en)

上面的EvenIterators类实现了一个偶数迭代器。从这个例子我们可以看出,只要我们实现了迭代协议,即方法__iter__()和next(),我们就实现了iterator。

5.关于迭代问题

那什么是关于迭代问题呢?我们可以先看一下下面这段代码:

list = [1,2,3,4]

list_iterator = iter(list)

for item in list_iterator:

print("第一次打印--",item)

for item in list_iterator:

print("第二次打印--",item)

第一次打印-- 1

第一次打印-- 2

第一次打印-- 3

第一次打印-- 4

从上面可以看出,我的迭代器用完了就没有了。上面使用了第二个for循环没有打印出什么东西来,其实如果使用__next__()方法,没有数据的话也会抛出异常。那我们怎么去解决这个问题呢?我们可能想到我创建另一个迭代器,然后去遍历另外一个迭代器。但其实赋值赋给的是地址值,说白了就是他们访问的是同一块内存地址。这样我们就很清楚如何去解决了。因为list中没有其他的引用类型,所以这个时候使用浅copy和深copy都能解决问题。(当时不能直接使用list_iterator.copy()这种浅复制,因为会抛出没有这个方法的异常,也就是说iterator中没有这个copy()方法)

list = [1,2,3,4]

list_iterator = iter(list)

list_iterator2 = list_iterator

print(list_iterator.__next__())

print(list_iterator2.__next__())

print(list_iterator.__next__())

print(list_iterator2.__next__())

我们不能对迭代器进行切片浅赋值,也不能直接调用copy方法进行浅复制(因为list中有,但是迭代器中没有对应的方法)。所以只能使用copy模块来进行浅复制和深复制。浅复制

import copy

list = [1,2,3,4]

list_iterator = iter(list)

list_iterator2 = copy.copy(list_iterator)

for item in list_iterator:

print(item)

for item in list_iterator2:

print(item)

1

2

3

4

1

2

3

4深复制

import copy

list = [1,2,3,4]

list_iterator = iter(list)

copy_list_iterator = copy.deepcopy(list_iterator)

for item in list_iterator:

print(item)

for item in copy_list_iterator:

print(item)

1

2

3

4

1

2

3

4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值