.pop从列表中删除项目会导致python

时间:2020-07-28 02:02:05

标签: python scope pycharm global-variables shadowing

这使我变得非常疯狂,因此任何帮助将不胜感激。我有一个程序在其中遍历函数中的列表。这是问题的玩具模型:

masterList = ["person","woman","man","camera","television"]
workingList = masterList

def removeItem (workingList):
    item = workingList.pop(2)
    print("Test 1:",workingList)


removeItem(workingList)

print("Test 2:", workingList)
print("Test 3:", masterList)

如预期的那样,“测试1”将打印出删除了项目的列表。
但是,“测试2”也会打印出删除了项目的列表。我没想到,但是没关系。这不是真正的问题,但是我敢肯定,在这里我对可变范围和可变阴影不了解。

没有真正的问题是“测试3”,如您所见,它正在打印出母版列表,该列表甚至不应该被removeItem功能或其中的pop函数。但是,它也正在打印出已删除项目的列表。

这怎么可能发生,我该如何预防?

非常感谢!

干杯, 阿里

3 个答案:

答案 0 :(得分:3)

Python列表是可变对象。

m = list([1, 2, 3])
n = m

a = 5
b = a

id(a) == id(b)
# id() return "identity" of the object.
# True,  Both a and b are references to the same object. 
id(m) == id(n)
# True,  Both m and n are references to the same object. 

b = b + 2 
id(a) == id(b)
# False, a new object on separate location is created, which b will point.

n.pop()
id(m) == id(n)
# True, the object is mutated, and m and n still references to the same object.

由于python列表是可变的,所以突变后m和n仍将引用同一对象。而对于像int这样的不可变对象,将创建一个新对象,并且标识符将引用该新对象。

要点是,在您的方案中,由于python列表是可变的,因此只有一个对象。

但是,如果在修改新列表时需要保持原始列表不变,则可以使用copy()方法。

new_list = original_list.copy()

new_listoriginal_list的ID不同。

在此处详细了解可变性:https://medium.com/@meghamohan/mutable-and-immutable-side-of-python-c2145cf72747

答案 1 :(得分:2)

您必须复制masterList,否则workingList只是参考。

如果您的list不包含其他容器(您的容器没有),则浅拷贝就足够了。进行浅表复制的方法有很多,但是slicing是最佳选择。

masterList = ["person","woman","man","camera","television"]
workingList = masterList[:] #copy via slice

用于制作浅表副本的其他方式

workingList = masterList * 1
workingList = masterList.copy()
workingList = list(masterList)
workingList = [*masterList]

import copy
workingList = copy.copy(masterList)

如果您的list确实拥有保存引用的内容(例如其他容器,类等),那么您需要制作一个deepcopy

import copy
a = [[1, 2, 3], ['a', 'b', 'c']]
b = copy.deepcopy(a)

答案 2 :(得分:1)

好像我想通了。这两个列表实际上是相同的列表,除非您使用import bs4 from urllib.request import urlopen as uReq from bs4 import BeautifulSoup as soup my_url = 'https://www.rottentomatoes.com/top/bestofrt/' # grabbing connection uClient = uReq(my_url) page_html = uClient.read() uClient.close() # html parser page_soup = soup(page_html, "html.parser") # gather movies containers = page_soup.findAll("table", {"class":"table"}) for container in containers: movie_rank_container = container.findAll("td", {"class":"bold"}) movie_name_container = container.findAll("a", {"class":"unstyled articleLink"}) movie_rating_container = container.findAll("td", {"class":"right hidden-xs"}) for movie_rank, movie_names, movie_rating in zip(movie_rank_container, movie_name_container, movie_rating_container): print("Rank: " + movie_rank.text) print("Name: " + movie_names.text.strip()) print("Rating: " + movie_rating.text)

因此,将前两行替换为:

list.copy()

使一切按预期执行!好吧,我仍然不能说我了解变量作用域是如何整体发挥作用的,但这至少可以解决主要问题。