我的问题非常简单。
for
循环是否每次都会计算它使用的参数?
如:
for i in range(300):
python是否为此循环的每次迭代创建了300个项目的列表?
如果是,这是一种避免它的方法吗?
lst = range(300)
for i in lst:
#loop body
对于像这样的代码示例也一样。
for i in reversed(lst):
for k in range(len(lst)):
每次都应用反向过程,还是每次迭代计算的长度? (我问这个python2和python3)
如果没有,Python如何在迭代迭代时评估迭代的变化?
答案 0 :(得分:7)
不用担心,迭代器只会被评估一次。它最终大致相当于这样的代码:
it = iter(range(300))
while True:
try:
i = next(it)
except StopIteration:
break
... body of loop ...
请注意,它不是相当等效,因为break
的工作方式不同。请注意,您可以将else
添加到for
循环,但这不适用于上述代码。
答案 1 :(得分:4)
创建的对象取决于循环返回的Iterable的__iter__
方法。
通常Python在迭代Iterable时创建一个Iterator,Iterable本身不是Iterator。在Python2中,range
返回一个列表,该列表是一个Iterable,并且有一个__iter__
方法,它返回一个Iterator。
>>> from collections import Iterable, Iterator
>>> isinstance(range(300), Iterable)
True
>>> isinstance(range(300), Iterator)
False
>>> isinstance(iter(range(300)), Iterator)
True
for in sequence: do something
语法基本上是执行此操作的简写:
it = iter(some_iterable) # get Iterator from Iterable, if some_iterable is already an Iterator, __iter__ returns self by convention
while True:
try:
next_item = next(it)
# do something with the item
except StopIteration:
break
这是一个包含一些打印语句的演示,用于阐明使用for循环时发生的情况:
class CapitalIterable(object):
'when iterated over, yields capitalized words of string initialized with'
def __init__(self, stri):
self.stri = stri
def __iter__(self):
print('__iter__ has been called')
return CapitalIterator(self.stri)
# instead of returning a custom CapitalIterator, we could also
# return iter(self.stri.title().split())
# because the built in list has an __iter__ method
class CapitalIterator(object):
def __init__(self, stri):
self.items = stri.title().split()
self.index = 0
def next(self): # python3: __next__
print('__next__ has been called')
try:
item = self.items[self.index]
self.index += 1
return item
except IndexError:
raise StopIteration
def __iter__(self):
return self
c = CapitalIterable('The quick brown fox jumps over the lazy dog.')
for x in c:
print(x)
输出:
__iter__ has been called
__next__ has been called
The
__next__ has been called
Quick
__next__ has been called
Brown
__next__ has been called
Fox
__next__ has been called
Jumps
__next__ has been called
Over
__next__ has been called
The
__next__ has been called
Lazy
__next__ has been called
Dog.
__next__ has been called
如您所见,__iter__
仅被称为一次,因此只创建了一个Iterator对象。
答案 2 :(得分:0)
在这种情况下,Range会创建一个包含300个整数的数组。它不会创建300次300次的数组。并不是每一项都有效。如果你使用xrange,它将创建一个可迭代的对象,它不会占用几乎同样多的内存。 https://docs.python.org/2/library/functions.html#xrange
for i in xrange(300): #low memory foot print, similar to a normal loop
print(i)