Python list vs.循环引用会发生什么

时间:2016-11-30 20:33:37

标签: python object reference

这是我的例子,按预期工作

import pandas as pd

df_1 = pd.DataFrame({'A': [1,1]})
df_2 = pd.DataFrame({'A': [2,1]})

df_list = [df_1, df_2]
df_list = [x.loc[x['A'] == 1] for x in df_list]

print(df_list[0])
print('____')
print(df_list[1])

这是输出:

   A
0  1
1  1
____
   A
1  1

这是一个例子,我希望产生类似的输出,但它没有:

import pandas as pd

df_1 = pd.DataFrame({'A': [1,1]})
df_2 = pd.DataFrame({'A': [2,1]})

df_list = [df_1, df_2]

for el in df_list:
    el = el.loc[el['A']==1]

print(df_list[0])
print('____')
print(df_list[1])

这是输出

   A
0  1
1  1
____
   A
0  2
1  1

第二个例子有什么问题。我猜测参考一个对象发生了什么,我在哪里可以阅读更多关于它的内容?

1 个答案:

答案 0 :(得分:1)

在第一个场景中,您通过列表解析重写df_list。第二个迭代数据帧列表,但从不更改数据帧本身。它们的关键是列表推导实际上返回一个新列表,并重写df_list。

这是一个说明性的例子(原谅所有的印刷语句......):

lst = ['a', 'b']
print('Memory address of the list: %s' % hex(id(lst)))
print('--'*10)
print('BEGIN FOR LOOP')
print('--'*10)
for letter in lst:
    letter = 'c'
print(lst)
print('Memory address of the list: %s' % hex(id(lst)))
print('--'*10)
print('Now use a list comprehension, which will return a new list')
lst = ['c' for letter in lst]
print(lst)
print('Memory address of the list: %s' % hex(id(lst)))
print(letter) # letter is still a variable that has been declared

输出:

Memory address of the list: 0x10b45b2c8
--------------------
BEGIN FOR LOOP
--------------------
['a', 'b']
Memory address of the list: 0x10b45b2c8  # Same list
--------------------
Now use a list comprehension, which will return a new list
['c', 'c']
Memory address of the list: 0x10b455b08  # New list, new memory spot

请注意,使用列表推导后,内存地址实际上已更改。这意味着你要查看一个全新的对象。在for循环之后,您将查看相同的旧列表。在for循环中,您创建变量el并在每次迭代时重新分配它。

这样可以满足您的期望,因为您将新值存储到新列表中:

import pandas as pd

df_1 = pd.DataFrame({'A': [1,1]})
df_2 = pd.DataFrame({'A': [2,1]})

df_list = [df_1, df_2]

lst = []
for el in df_list:
    lst.append(el.loc[el['A']==1])

print(lst[0])
print('____')
print(lst[1])