Python函数内修改参数避免创建新对象的解决方案(游戏统计场景)
这个问题在Python里真的太常见啦——毕竟int是不可变类型,函数里执行games +=1其实是创建了一个新的整数对象,根本碰不到外面的那个games变量。给你几个简洁实用的解决方案,挑适合你的场景来用:
1. 返回更新后的变量值(最推荐,Pythonic风格)
这是最符合Python设计哲学的方式:让check()把更新后的games和wins跟原来的返回结果一起返回,然后在调用处重新赋值给外部变量。
修改后的代码示例:
def check(...games, wins,...): ... games += 1 # 简化三元表达式,提升可读性 wins += 1 if winner == 'agent' else 0.5 if winner == 'bot' else 0 ... # 把业务返回值和更新后的状态值一起返回 return 1, games, wins # 另一个分支同理 return 0, games, wins def play_bot(): games = 0 wins = 0 ... # 同时接收返回结果和更新后的变量 result, games, wins = check(...games, wins,...) if result: player = choice([0,1]) ...
这种方式逻辑清晰,没有隐藏的副作用,别人读代码的时候一眼就能看明白状态是怎么传递的。
2. 用可变容器包裹变量(不想改返回逻辑时用)
列表、字典这类可变类型在函数里修改元素时,会直接作用于原对象。我们可以把games和wins放进列表里传进函数,直接修改列表的元素。
代码示例:
def check(...games_list, wins_list,...): ... # 修改列表的第一个元素,直接作用于外部的列表 games_list[0] += 1 wins_list[0] += 1 if winner == 'agent' else 0.5 if winner == 'bot' else 0 ... return 1 return 0 def play_bot(): # 用列表把变量包裹起来 games = [0] wins = [0] ... if check(...games, wins,...): player = choice([0,1]) # 后续使用时取列表的第一个元素即可 print(f"总游戏数: {games[0]}, 获胜数: {wins[0]}") ...
这种方式不用改动check()的返回值逻辑,但可读性稍差一点,需要记住是操作列表元素。
3. 用类封装状态(适合复杂游戏逻辑)
如果你的游戏后续要加更多状态(比如平局数、胜率统计、玩家等级等),把这些状态封装到类里会更清晰。check()作为类的方法,直接操作实例的属性。
代码示例:
class GameSession: def __init__(self): self.total_games = 0 self.agent_wins = 0 def check(self, ...): # 直接操作实例属性,不需要传参 self.total_games += 1 self.agent_wins += 1 if winner == 'agent' else 0.5 if winner == 'bot' else 0 ... return 1 return 0 def play_bot(): # 创建一个游戏会话实例 session = GameSession() ... # 直接调用实例方法,自动维护状态 if session.check(...): player = choice([0,1]) # 随时获取最新状态 print(f"总游戏数: {session.total_games}, 代理获胜数: {session.agent_wins}") ...
这种方式扩展性极强,后续新增状态只需要在类里加属性即可,代码结构也更整洁。
内容的提问来源于stack exchange,提问作者Saxt
相关产品推荐
相关产品推荐

