您的list_flatten
函數改變了lst1
的參數,所以您並不需要返回任何東西。你可以這樣調用:
L = [1,[2,['a',(3,'b')]],(5,6),([11,22])]
def list_flatten(lst, lst1):
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
Lflat = []
list_flatten(L, Lflat)
print(Lflat)
輸出
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
我們推薦使用isinstance
,而不是type
,因爲這使代碼更靈活:它也將與list
派生對象。
我們可以重新寫的功能,使您不必在lst1
經過:
def list_flatten(lst, lst1=None):
if lst1 is None:
lst1 = []
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
return lst1
Lflat = list_flatten(L)
print(Lflat)
我們給lst1
的None
和我們遞歸的最高級別重新綁定默認值名稱lst1
到一個空的列表來收集結果。
我們不能給lst1
默認值[]
。這是因爲默認參數是在編譯函數時創建的,而不是在函數被調用時創建的,並且如果我們給lst1
默認值[]
,那麼在每次調用時將使用相同的列表。它看起來像我們第一次使用list_flatten
時所做的那樣,但在隨後的調用中它不會像預期的那樣運行。這是一個簡短的演示。
L = [1,[2,['a',(3,'b')]],(5,6),([11,22])]
def list_flatten(lst, lst1=[]):
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
return lst1
Lflat = list_flatten(L)
print(Lflat)
Lflat = list_flatten(L)
print(Lflat)
輸出
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22, 1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
正如你所看到的,lst1
已經從第一個呼叫保留其內容。有關此重要主題的更多信息,請參閱「Least Astonishment」 and the Mutable Default Argument。有些時候這種行爲是可取的,但在這種情況下,向代碼添加註釋是明智的,即您有意使用可變默認參數。
還有一種方法是使list_flatten
成發電機,並收集其輸出到一個列表:
def list_flatten(lst):
for item in lst:
if isinstance(item, list):
yield from list_flatten(item)
else:
yield item
Lflat = list(list_flatten(L))
print(Lflat)
在最新版本的Python可以用[*list_flatten(L)]
取代list(list_flatten(L))
。
Python 2裏沒有yield from
,但你可以替換該行:
for u in list_flatten(item):
yield u
如果你實際上並不需要的列表,你可以調用發電機是這樣的:
for u in list_flatten(L):
print(u)
輸出
1
2
a
(3, 'b')
(5, 6)
11
22
'([])'是一個列表,因爲[元組由數值的由逗號分隔的](https://docs.python.org/2/tutorial /datastructures.html#tuples-and-sequences),並且這裏沒有逗號。在這種情況下,括號只是強制評估*裏面的*括號,它是一個列表。 –
'([],)'是一個元組。別擔心,這讓每個人都感到困惑。 –
@DavidZemens確實如此,但函數會改變'lst1',所以它確實不需要返回任何東西。 –