You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python嵌套字典更新异常:指定子字典更新却同步修改所有子字典

嵌套字典同步修改问题:爬虫数据存入字典时所有子字典被同步更新

使用BeautifulSoup抓取网页表格数据,遍历行与单元格提取车手名称和圈速,试图存入嵌套字典。但运行时发现,更新指定一级键对应的二级字典后,所有一级键的二级字典都被同步修改。

代码示例

# Imports
import requests
from bs4 import BeautifulSoup as bsoup

dataurls = {
    'race1': 'https://fiaresultsandstatistics.motorsportstats.com/results/2022-bahrain-grand-prix/classification/2c65d50d-606e-4988-81c5-7a4976ef0e6f'
}

# Setup the dictionary
races = ['race1', 'race2']
drivers = ['driver1', 'driver2']
mainDict = dict.fromkeys(races, {})

# Scraping elements
def webscraper(mDict, race):
    soup = bsoup(requests.get(dataurls[race]).content, "html.parser")
    # Dict for races, will contain driver key and lap time value.
    rDict = {}
    # Parse the table by row, extract driver name and lap time
    for tr in soup.find("table", class_="_2Q90P").find_all("tr", class_="_3AoAU"):
        row = ([td.text for td in tr.find_all('td')])
        dDriver = row[2]
        dTime = row[6]
        dDict = {dDriver: dTime}
        rDict.update(dDict)
    mDict[race].update(rDict)

webscraper(mainDict, races[0])
print(mainDict)

预期输出

{
'race1': {'driver1': '1:30:100', 'driver2': '1:30.200'},
'race2': {}
}

实际输出

{
'race1': {'driver1': '1:30:100', 'driver2': '1:30.200'}, 
'race2': {'driver1': '1:30:100', 'driver2': '1:30.200'}
}

问题根源

dict.fromkeys(races, {}) 初始化字典时,所有一级键指向的是同一个空字典对象。也就是说,mainDict['race1']和mainDict['race2']引用的是内存中的同一个字典实例,修改其中一个,另一个自然会同步变化。

解决方法

用字典推导式初始化mainDict,为每个赛事创建独立的空字典:

mainDict = {race: {} for race in races}

修改后重新运行代码,即可得到符合预期的输出:race1包含抓取到的车手数据,race2保持空字典。

补充方案

如果不想修改初始化逻辑,也可以在webscraper函数中提前检查并创建独立字典:

def webscraper(mDict, race):
    # 确保当前赛事对应独立字典
    if race not in mDict or not isinstance(mDict[race], dict):
        mDict[race] = {}
    soup = bsoup(requests.get(dataurls[race]).content, "html.parser")
    rDict = {}
    for tr in soup.find("table", class_="_2Q90P").find_all("tr", class_="_3AoAU"):
        row = ([td.text for td in tr.find_all('td')])
        dDriver = row[2]
        dTime = row[6]
        rDict[dDriver] = dTime
    mDict[race].update(rDict)

不过字典推导式的方式更简洁高效,是此类场景的首选方案。

内容的提问来源于stack exchange,提问作者CleanGiant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:33:23