为何areas列表各元素href数据重复,id和name却能正确区分?
问题解答
原因分析
核心问题是浅拷贝导致的可变对象引用复用:
- 你用
areaInfo = dict(areaDict)做的是浅拷贝操作。对于字典里的不可变值(比如字符串类型的id、name),浅拷贝会直接复制值;但对于urls对应的嵌套列表这种可变对象,浅拷贝只会复制列表的内存引用,而非创建新的列表实例。 - 循环中所有
areaInfo['urls']其实都指向同一个列表对象,每次修改areaInfo['urls'][0][1]都是在修改同一块内存里的内容,最终所有元素的urls都会被最后一次循环的赋值覆盖。 - 而
id和name是不可变类型,每次赋值都会生成新的独立对象,不会共享引用,所以能正确区分不同项。
修复方案
方案1:手动初始化urls,避免引用复用
在循环内创建areaInfo时,重新初始化urls,不再复用模板字典里的列表引用:
areaDict = { "id": "", "name": "", } areas = [] def getCouncils(): page = requests.get('https://profile.id.com.au/') soup = BeautifulSoup(page.content, 'html.parser') links = soup.select("a.councilCard") id = 0 for anchor in links: areaInfo = dict(areaDict) areaInfo['id'] = id id += 1 areaInfo['name'] = anchor.text.strip() # 手动创建新的urls列表,避免引用复用 areaInfo['urls'] = [["profileID", anchor['href']], ["", ""]] areas.append(areaInfo)
方案2:使用深拷贝复制整个字典
通过copy.deepcopy实现完全拷贝,包括嵌套层级的所有可变对象:
import copy areaDict = { "id": "", "name": "", "urls": [["", ""], ["", ""]], } areas = [] def getCouncils(): page = requests.get('https://profile.id.com.au/') soup = BeautifulSoup(page.content, 'html.parser') links = soup.select("a.councilCard") id = 0 for anchor in links: # 深拷贝复制所有层级的对象,避免引用共享 areaInfo = copy.deepcopy(areaDict) areaInfo['id'] = id id += 1 areaInfo['name'] = anchor.text.strip() areaInfo['urls'][0][0] = "profileID" areaInfo['urls'][0][1] = anchor['href'] areas.append(areaInfo)
方案3:直接在循环内构造新字典
抛弃模板字典,每次循环直接创建独立的areaInfo,逻辑最直观:
areas = [] def getCouncils(): page = requests.get('https://profile.id.com.au/') soup = BeautifulSoup(page.content, 'html.parser') links = soup.select("a.councilCard") id = 0 for anchor in links: areaInfo = { "id": id, "name": anchor.text.strip(), "urls": [["profileID", anchor['href']], ["", ""]] } id += 1 areas.append(areaInfo)
内容的提问来源于stack exchange,提问作者AlohaAbar
相关产品推荐
相关产品推荐

