2016-10-08 55 views
0

範圍()如何區分正在進行的呼叫?'range()'如何在內部工作?

例子:

def ex(): 
    list = [1,2,3,4] 
    for val in range(len(list)): 
     print(val) 
     break 
    for val in range(len(list)): 
     print(val) 
     break 

輸出 -

0 
0 

總之,我的問題是,爲什麼不輸出產量這樣?

0 
1 

期間)在「第一個for循環」第一次調用的範圍(,該呼叫是「範圍(LEN(列表))」, 並且在到的範圍中的第一個呼叫() 'second for loop',這個調用是'range(len(list))',它等於第二次調用'first for loop'中的range()。 range()如何知道這個調用是從'second for loop'而不是'for first for loop'?

+0

'range()'帶有1個參數,返回一個迭代器,從0開始,直到'arg'遞增。第一個for循環不會重複調用它。然後你打破第一個循環,開始一個新的循環,再次調用'range()'返回一個從0開始的迭代器。 – AChampion

+0

爲什麼它會產生輸出?循環不會從另一個停止的位置開始,並且在第一次迭代中斷裂。 – Li357

+0

答案(標題中的問題)取決於你使用的Python版本。 Python 3'range'與Python 2不同。另外 - 不要使用'list'作爲標識符。它會覆蓋一個內置的名稱。 –

回答

6

我不知道爲什麼你期望range記住,它以前被稱爲。這個班級不保留任何有關以前通話的狀態;它只是做你的問題。每調用一次range(x)時,都會返回一個新的range對象,該對象在您遍歷它時提供從0到x-1之間的數字。每次通話都獨立於以前的任何通話。

爲了得到你所描述的行爲,你需要重複使用相同迭代在每個循環中range對象。

Python 3.5.1 (default, Apr 18 2016, 11:46:32) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.29)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> l = [1,2,3,4] 
>>> r = range(len(l)) 
>>> for val in r: 
... print(val) 
... break 
... 
0 
>>> for val in r: 
... print(val) 
... break 
... 
0 
>>> i = iter(r) 
>>> for val in i: 
... print(val) 
... break 
... 
0 
>>> for val in i: 
... print(val) 
... break 
... 
1 

您可以形象,像

for x in xs: 
    do_something(x) 

是短期的

i = iter(xs) 
while True: 
    try: 
     x = next(i) 
    except StopIteration: 
     break 
    do_something(x) 

iter如果它已經返回其說法,事實上,迭代器,所以每for循環在嘗試迭代ove時會返回新的初始迭代器r是非迭代器可迭代的。

+0

每個調用都會返回一個用給定序列(0,1,...)初始化的新Iterator對象。這個迭代器是「範圍對象」,但我認爲正確的術語是迭代器。 for循環調用「next」函數來實際遍歷序列。 – DanJ

+0

範圍對象本身不是迭代器;在兩個循環中使用'r'仍然會在問題中產生輸出,因爲每個'for'循環都會從''range'對象(通過'r .__ iter__')獲取一個新的迭代器。 – chepner

+2

迭代器是提供'__next__'方法的東西,而* iterable *則是提供'__iter__'方法的東西。 'range'定義'__iter__',但不是'__next__'。 ('range .__ iter__'返回'range_iterator'的一個實例,它是定義'__next__'的類)。 – chepner