Python for循环如何计算其参数
我的问题很简单Python for循环如何计算其参数,python,python-2.7,python-3.x,for-loop,Python,Python 2.7,Python 3.x,For Loop,我的问题很简单 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)): 是每次应用反向过程,还是每次迭代计算长度?(我对蟒蛇2和蟒蛇3都这样要求)
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)):
是每次应用反向过程,还是每次迭代计算长度?(我对蟒蛇2和蟒蛇3都这样要求)
如果不是,Python在迭代iterable时如何计算iterable上的更改?不用担心,迭代器将只计算一次。它最终大致相当于这样的代码:
it = iter(range(300))
while True:
try:
i = next(it)
except StopIteration:
break
... body of loop ...
请注意,它不是完全等效的,因为
break
的工作方式不同。请记住,您可以将else
添加到for
循环中,但这在上述代码中不起作用。在这种情况下,Range会创建一个300整数的数组。它不会创建300整数的数组300次。它不是很有效率。如果您使用xrange,它将创建一个不会占用太多内存的iterable对象
示例.py
创建什么对象取决于在返回上循环的Iterable的
\uuuuu iter\uuuu
方法
通常,Python在迭代本身不是迭代器的Iterable时会创建一个迭代器。在Python2中,range
返回一个列表,该列表是一个Iterable,具有一个返回迭代器的\uuuuuuuuuuu
方法
>>> from collections import Iterable, Iterator
>>> isinstance(range(300), Iterable)
True
>>> isinstance(range(300), Iterator)
False
>>> isinstance(iter(range(300)), Iterator)
True
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
如您所见,\uu iter\uu
只被调用一次,因此只创建了一个迭代器对象。或者在Python2或Python3中,i=next(it)
。此外,尽管在整个循环中使用的是同一个迭代器,但它所迭代的对象可能会发生变化,这就是为什么不建议这样做的原因,例如,在迭代列表元素时修改列表。谢谢,我刚刚找到了一种方法来检查我所问的问题。我可以定义一个返回iterable(不是生成器)的函数,在其中添加一个print语句,然后检查它将打印多少次。如果您对优化感兴趣,我会看看“将代码转换为漂亮的、惯用的Python”-很多很棒的Python代码。您已经得到了答案,但值得一提的是这个范围()仅返回Python 2中的列表。在Python3中,range(300)
创建一个range对象,它是一个具有内部状态的生成器。这意味着您可以在不耗尽内存的情况下执行诸如range(10000000000000000)
之类的操作。在Python2中,可以使用xrange
获得相同的效果。
__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