Python字典列表赋值异常:所有元素均为最后一项值
问题
处理字典列表时出现异常:循环中打印的id依次为1、2、3…,但最终self.template_json的所有元素均为最后一项数据,而非预期的对应id值。
执行代码
for i in range(len(self.dict_trie_csv_infos)): self.template_json.append(self.template_json[0]) #add values to json for i in range(len(self.dict_trie_csv_infos)): self.template_json[i]['id'] = self.dict_trie_csv_infos[i]['id'] print(self.template_json[i]['id']) self.template_json[i]['name'] = self.dict_trie_csv_infos[i]['name'] self.template_json[i]['title'] = self.dict_trie_csv_infos[i]['event title'] self.template_json[i]['startDateTime'] = self.dict_trie_csv_infos[i] #fill the smart contract now self.template_json[i]['ticketCollection'][0]['collectionName'] = self.dict_trie_csv_infos[i]['smart_contract']['collectionName'] self.template_json[i]['ticketCollection'][0]['endTime'] = self.dict_trie_csv_infos[i]['smart_contract']['sale_params']['end_time'] self.template_json[i]['ticketCollection'][0]['pricePerToken'] = self.dict_trie_csv_infos[i]['smart_contract']['sale_params']['price_per_token'] self.template_json[i]['ticketCollection'][0]['totalTicketsCount'] = '' self.template_json[i]['ticketCollection'][0]['soldTicketsCount'] = '' print(self.template_json[0])
异常表现
循环中打印id正常,但最终self.template_json[0]输出为最后一项数据:
{'id': '4', 'name': 'Stade de France', 'title': 'Coldplay World Tour', 'startDateTime': 1651615200, 'endDateTime': 1659045600, 'address': '', 'locationName': '93200 Saint-Denis', 'totalTicketsCount': '10000', 'assetUrl': 'https://coldplay.com/coldplay_asset.mp4', 'lineup': [''], 'ticketCollection': [{'collectionName': 'KT2jH58CPkYBe3bRuTCET6A4NhnosX2BAnp9', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': 50, 'maxMintPerUser': '', 'saleSize': '', 'endTime': 1659045600, 'totalTicketsCount': '', 'soldTicketsCount': ''}], 'adress': 'KT1ffDxCJH9EPimNm19ifBEgG9bFRgptJwop'}
前置数据
- 循环前的
template_json结构:
[{'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}, {'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}, {'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}, {'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}, {'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}, {'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': ''}]}]
dict_trie_csv_infos示例数据:
{'event_id': 1, 'collection_name': 'Mouse On', 'smart_contract': {'multisig': 'KT1Aer6TxNwoMJejoqsNP8TEN7J6STgMtJcA', 'sale_params': {'is_presale': False, 'metadata_list': [], 'price_per_token': 4, 'max_mint_per_user': 5, 'sale_size': 500, 'sale_currency': {'xtz': None}, 'start_time': 1656626400, 'end_time': 1657490400}, 'collectionName': 'KT1Apf8CPkYBe3bRuTCET6A4NhnosX2BAnp9', 'scAddress': 'KT1AKqxCJH9EPimNm1wo1BEgG9bFRgptJwkk'}, 'id': '1', 'event title': 'Mouse Party', 'event start date': '10/07/2022 18:30', 'event end date': '11/07/2022 01:00', 'name': "L'Astrolabe", 'address of the location': '1 Rue Alexandre Avisse 45000 Orléans', 'total ticket number': '500', 'maximum tickets per user': '5', 'sale start date': '01/07/2022', 'line up': 'Mehdi Maïzi-Rad Cartier-Squidji', 'asset url': 'https://photos.com/mouseparty.png', 'lineup': ['Mehdi Maïzi', 'Rad Cartier', 'Squidji']}
预期self.template_json[0]的id值为1,但实际得到最后一项的id值4。
问题原因
Python中字典是引用类型,代码里self.template_json.append(self.template_json[0])是把self.template_json[0]这个字典对象的引用重复添加到列表中。也就是说,self.template_json里的所有元素其实指向的是同一个字典对象。
后续循环修改self.template_json[i]时,本质上都是在修改同一个字典,所以最后所有元素都会变成最后一次修改的结果。循环中打印id正常是因为每次修改后立刻打印的是当前字典的状态,但后续修改会覆盖之前的内容。
解决方案
需要为每个循环创建一个独立的字典副本,而不是复用同一个引用。由于字典包含嵌套的列表和子字典,必须使用copy.deepcopy()实现深拷贝,避免嵌套对象仍共享引用。
修改后的代码
import copy # 替换原有的添加元素循环,生成独立的字典副本 for i in range(len(self.dict_trie_csv_infos)): new_item = copy.deepcopy(self.template_json[0]) self.template_json.append(new_item) # 填充数据的循环保持不变 for i in range(len(self.dict_trie_csv_infos)): self.template_json[i]['id'] = self.dict_trie_csv_infos[i]['id'] print(self.template_json[i]['id']) self.template_json[i]['name'] = self.dict_trie_csv_infos[i]['name'] self.template_json[i]['title'] = self.dict_trie_csv_infos[i]['event title'] self.template_json[i]['startDateTime'] = self.dict_trie_csv_infos[i] # 填充智能合约数据 self.template_json[i]['ticketCollection'][0]['collectionName'] = self.dict_trie_csv_infos[i]['smart_contract']['collectionName'] self.template_json[i]['ticketCollection'][0]['endTime'] = self.dict_trie_csv_infos[i]['smart_contract']['sale_params']['end_time'] self.template_json[i]['ticketCollection'][0]['pricePerToken'] = self.dict_trie_csv_infos[i]['smart_contract']['sale_params']['price_per_token'] self.template_json[i]['ticketCollection'][0]['totalTicketsCount'] = '' self.template_json[i]['ticketCollection'][0]['soldTicketsCount'] = '' print(self.template_json[0])
更简洁的替代方案
如果模板结构固定,可以直接在循环中创建新的字典对象,避免依赖原有列表的模板:
import copy # 定义固定模板结构 TEMPLATE = { 'id': '', 'name': '', 'title': '', 'startDateTime': '', 'endDateTime': '', 'address': '', 'locationName': '', 'totalTicketsCount': '', 'assetUrl': '', 'lineup': [], 'ticketCollection': [{ 'collectionName': '', 'scAddress': '', 'collectionAddress': '', 'pricePerToken': '', 'maxMintPerUser': '', 'saleSize': '', 'endTime': '', 'totalTicketsCount': '', 'soldTicketsCount': '' }] } # 清空原有列表,重新生成数据 self.template_json = [] for info in self.dict_trie_csv_infos: new_item = copy.deepcopy(TEMPLATE) new_item['id'] = info['id'] new_item['name'] = info['name'] new_item['title'] = info['event title'] new_item['startDateTime'] = info new_item['ticketCollection'][0]['collectionName'] = info['smart_contract']['collectionName'] new_item['ticketCollection'][0]['endTime'] = info['smart_contract']['sale_params']['end_time'] new_item['ticketCollection'][0]['pricePerToken'] = info['smart_contract']['sale_params']['price_per_token'] self.template_json.append(new_item) print(self.template_json[0])
内容的提问来源于stack exchange,提问作者guiguilecodeur
相关产品推荐
相关产品推荐

