2016-11-14 51 views
1

我正在Python中的列表上做一個for循環,據我所知,應該爲列表中的每個元素創建一個淺表副本。但是,當我對元素執行操作時,更改沒有反映在原始列表中。For循環在python不操縱原始對象,而是執行深度複製

下面的代碼:

interactions = f.readlines() 
for interaction in interactions: 
    orig = interaction 
    interaction = interaction.replace('.', '').replace(' ', '').strip('\n') 
    if len(interaction) == 0: 
     interactions.remove(orig) 

    print(interactions) 

此操作的給定的['. Bph\n', 'Cardiovascular\n', 'Diabetes\n', '. ']的初始列表的輸出是:

['. Bph\n', 'Cardiovascular\n', 'Diabetes\n', '. '] 
['. Bph\n', 'Cardiovascular\n', 'Diabetes\n', '. '] 
['. Bph\n', 'Cardiovascular\n', 'Diabetes\n', '. '] 
['. Bph\n', 'Cardiovascular\n', 'Diabetes\n'] 

即使當我按照調試器,我可以看到正在執行正確的操作在interaction上,但這些更改並未反映在交互中。我在這裏做錯了什麼?

+0

吉姆回答相當完美,但要記住,雖然Python的__does__在分配執行淺拷貝,'str'對象是不可改變的,因此沒有'str'方法將永遠修改對象。 –

回答

1

Python中的字符串是不可改變的,所以你或者需要用清理過的版本替換每個元素(使用Jim的答案中的索引)或者建立一個新列表。 IMO做到這一點的最巧妙的方法是用一個列表理解:

interactions = [i.replace('.', '').replace(' ', '').strip('\n') for i in interactions] 
interactions = list(filter(None, interactions)) # Remove empty elements 
+0

Jim對我出錯的地方給出了一個更好的描述,但這絕對是更清晰的解決方案。 – bendl

2

它爲什麼要反映?您正在修改str元素,並且它們無法在原位進行更改,包含已更改值的新字符串會返回;沒有反映在原始列表中。 :-)

相反,你應該遍歷的interactions[:]副本,並使用該指數enumerate產生分配:

for i, interaction in enumerate(interactions[:]): 
    # redundant in this snippet 
    orig = interaction 
    # strip() will remove '\n' and leading-trailing ' ' 
    interaction = interaction.replace('.', '').replace(' ', '').strip('\n') 
    # if interaction: suffices 
    if len(interaction) == 0: 
     interactions.remove(orig) 
    else: 
     interactions[i] = interaction 
    print(interactions) 

這現在給的輸出:

['Bph', 'Cardiovascular\n', 'Diabetes\n', '. '] 
['Bph', 'Cardiovascular', 'Diabetes\n', '. '] 
['Bph', 'Cardiovascular', 'Diabetes', '. '] 
['Bph', 'Cardiovascular', 'Diabetes']