Python字典作为函数参数时原模板字典被意外修改的问题咨询
Python字典传参后原字典被修改的问题解决
问题描述
我用初始字典做模板,按以下流程操作:
- 创建初始模板字典;
- 把字典传入函数,在函数内赋值给新变量操作;
- 向字典添加元素后返回给主代码的新变量;
- 重复步骤处理另一个变量,每次复用这个模板字典。
但实际运行时,初始模板字典也被同步更新,导致第二次传入时带着之前的脏数据。另外我原本以为全局的startDeck能被函数访问,但Python提示找不到它,而且所有字典(包括函数内临时字典)内容完全一样,搞不懂原因。
我的最小示例代码:
startDeck = { "deckSize":0, "score":0, "blackjack":False, } def playBlackjack(deck): userDeck = dealCards(cards= deck,count=2) compDeck = dealCards(cards= deck,count=1) def dealCards(cards,count): score = cards["score"] deckSize = cards["deckSize"] for n in range(count): newCard = {} deckSize+=1 score+=1 cardNo = "card" + str(deckSize) newCard["card"] = "hearts" newCard["value"] = 10 newCard["suit"] = "clubs" cards[cardNo]=newCard cards["score"]=score cards["deckSize"]=deckSize return cards playBlackjack(startDeck)
核心原因
Python里字典是可变对象,函数传参时传递的是对象的内存引用,不是创建新的副本。所以你在dealCards函数里修改cards字典的内容,本质上就是直接修改原字典(也就是startDeck)的内存数据——不管你有没有返回这个字典,原模板都会被改变。
至于“全局字典找不到”的问题,看你提供的代码是通过参数传递startDeck的,这种情况不会出现找不到的问题。如果你的实际代码是直接在函数里引用startDeck却没传参,那需要注意:如果要修改全局变量,必须在函数开头加global startDeck声明,否则Python会把它当成局部变量,抛出未定义的错误。
解决方法:传入字典的副本
要避免修改原模板字典,每次传入函数时,都要创建一个字典的拷贝,分两种情况:
- 浅拷贝:如果字典里没有嵌套的可变对象(比如你的
startDeck里都是数字、布尔值,没有嵌套字典/列表),用dict.copy()或者{**startDeck}即可。 - 深拷贝:如果字典里有嵌套的可变对象(比如某个键对应的值是另一个字典),需要用
copy.deepcopy(),前提是先导入copy模块。
修改后的示例代码
# 如果用深拷贝需要导入copy模块,浅拷贝不需要 import copy startDeck = { "deckSize":0, "score":0, "blackjack":False, } def playBlackjack(deck): # 传入浅拷贝的副本,避免修改原字典 userDeck = dealCards(cards= deck.copy(), count=2) # 或者用深拷贝:copy.deepcopy(deck) compDeck = dealCards(cards= deck.copy(), count=1) def dealCards(cards,count): score = cards["score"] deckSize = cards["deckSize"] for n in range(count): newCard = {} deckSize+=1 score+=1 cardNo = "card" + str(deckSize) newCard["card"] = "hearts" newCard["value"] = 10 newCard["suit"] = "clubs" cards[cardNo]=newCard cards["score"]=score cards["deckSize"]=deckSize return cards playBlackjack(startDeck) # 此时startDeck仍然是初始状态,不会被修改
内容的提问来源于stack exchange,提问作者Otispunkmeyer86
相关产品推荐
相关产品推荐

