generator and Iterator

用圆括号代替 list comprehensions 的 方括号,就是generator :

>>> list_comp = [x ** 2 for x in range(10) if x % 2 == 0]
>>> gen_exp = (x ** 2 for x in range(10) if x % 2 == 0)
>>> print(list_comp)
[0, 4, 16, 36, 64]
>>> print(gen_exp)
<generator object <genexpr> at 0x000001F455837E60>
>>> 

The type of data returned by list comprehensions and generator expressions differs.

>>> list_comp = [x ** 2 for x in range(10) if x % 2 == 0]
>>> gen_exp = (x ** 2 for x in range(10) if x % 2 == 0)
>>> print(list_comp)
[0, 4, 16, 36, 64]
>>> print(gen_exp)
<generator object <genexpr> at 0x7f600131c410>

迭代出来:

>>> for i in gen_exp:
	print(i)

	
0
4
16
36
64

注意,如果你再想迭代一次,就木有任何输出了,如下:

>>> gen_exp = (x ** 2 for x in range(10) if x % 2 == 0)
>>> for i in gen_exp:
	print(i)

	
0
4
16
36
64
>>> for i in gen_exp:
	print(i)

	
>>> 

为何第二次就是空的呢,难道迭代器只能用一次?
没错,用了一次以后,迭代器就耗尽了,你有一个正在迭代的缓冲区,你通过基本上移动指针来消耗一个缓冲区,随时读取。如果你已经读过一次,那么指针就在缓冲区的末尾,没有什么可读的。
The generator yields one item at a time — thus it is more memory efficient than a list:
如果你想重复使用呢?
那就定义一个函数。
见下文“The Syntax of Generator in Python 3”

>>> from sys import getsizeof
>>> my_comp = [x * 5 for x in range(1000)]
>>> my_gen = (x * 5 for x in range(1000))
>>> getsizeof(my_comp)
9024  
>>> getsizeof(my_gen)
88

可见要efficient 得多。
A list holds a number of values at once. But a Python generator holds only one value at a time, the value to yield. This is why it needs much less space compared to a list. With a generator, we also don’t need to wait until all the values are rendered.

The Syntax of Generator in Python 3
To create a python generator, we use the yield statement, inside a function, instead of the return statement. Let’s take a quick example.

>>> def counter():
     i=1
     while(i<=10):
          yield i
          i+=1

With this, we defined a Python generator called counter() and assigned 1 to the local variable i. As long as i is less than or equal to 10, the loop will execute. Inside the loop, we yield the value of I, and then increment it.

Then, we iterate on this generator using the for-loop.

>>> for i in counter():
	print(i)
	
1
2
3
4
5
6
7
8
9
10
>>> 

这个就可以使用多次:

>>> for i in counter():
	print(i)

	
1
2
3
4
5
6
7
8
9
10
>>> for i in counter():
	print(i)

	
1
2
3
4
5
6
7
8
9
10
>>> for i in counter():
	print(i)

	
1
2
3
4
5
6
7
8
9
10

Yielding into a Python List

This one’s a no-brainer. If you apply the list() function to the call to the Python generator, it will return a list of the yielded values, in the order in which they are yielded. Here, we take an example that creates a list of squares of numbers, on the condition that the squares are even.

def even_squares(x):
	for i in range(x):
		if i**2%2==0:yield i**2
>>> print(list(even_squares(10)))
[0, 4, 16, 36, 64]
>>> 

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××_______________________________
以下是Iterator
To build a python3 iterator, we use the iter() and next() functions. Let’s begin with iter() to create an iterator.

First, we create a list of events to store even numbers from 2 to 10.

>>> evens=[2,4,6,8,10]

Then, we apply the iter() function to this Python list to create a Python iterator object. We store it in the variable evenIterator.

>>> evenIterator=iter(evens)
>>> evenIterator
<list_iterator object at 0x000001A1179ACE10>

>>> next(evenIterator)
2
>>> next(evenIterator)
4
>>> next(evenIterator)
6
>>> next(evenIterator)
8
>>> next(evenIterator)
10
>>> next(evenIterator)
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    next(evenIterator)
StopIteration
>>> 

next()
You can also traverse the Python iterator using the next() method.

>>> evens=[2,4,6,8,10]
>>> evenIterator = iter(evens)
>>> evenIterator
<list_iterator object at 0x000001A1179A65C0>
>>> evenIterator.__next__()
2
>>> next(evenIterator)
4
>>> evenIterator.__next__()
6
>>> evenIterator.__next__()
8
>>> evenIterator.__next__()
10
>>> evenIterator.__next__()
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    evenIterator.__next__()
StopIteration
>>> 
>>> dir(evenIterator)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
>>> 

For-loop in Python Iterator
You can also use a for loop in python to iterate on an iterable like a python list or a python tuple.

>>> for i in 'Python':
	print(i)

	
P
y
t
h
o
n
>>> 

But how is this actually implemented? Let’s take a look.

>>> iter_obj=iter('Python')
>>> while True:
	try:
		i=next(iter_obj)
		print(i)
	except StopIteration:
		break

	
P
y
t
h
o
n
>>> 

So, this is how the above for loop is actually implemented.

How to Create Your Own Python Iterator?
Now you know how to use an iterator with the iter() and next() functions. But we won’t stop here. We will now start from scratch.

We implement the following class to create an iterator in Python for squares of numbers from 1 to max。

>> class PowTwo:
	def __init__(self,max=0):
		self.max = max
	def __iter__(self):
		self.n= 0
		return self
	def __next__(self):
		if self.n<=self.max:
			result = 2**self.n
			self.n+=1
			return result
		else :
			raise StopIteration
>>> a=PowTwo(4)
>>> i=iter(a)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
4
>>> next(i)
8
>>> next(i)
16
>>> next(i)
Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    next(i)
  File "<pyshell#60>", line 13, in __next__
    raise StopIteration
StopIteration
>>> 

Alternatively, you can use the iter() and next() methods for this object.

>>> j=a.__iter__()
>>> j.__next__()
1
>>> j.__next__()
2
>>> j.__next__()
4
>>> j.__next__()
8
>>> j.__next__()
16
>>> j.__next__()
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    j.__next__()
  File "<pyshell#60>", line 13, in __next__
    raise StopIteration
StopIteration
>>> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值