更改嵌套字典的值会更改其他嵌套字典的值
Changing the value of a nested dictionary changes other nested dictionary values
*抱歉,如果标题没有意义,我不确定如何表达它
所以我开始在 Pycord 的库中制作 python discord 机器人。我想制作一个可以在多台服务器上运行的机器人,并且每台服务器都有不同的值。因此,为此,我制作了一个字典,将所有这些值存储在一个嵌套字典中。但是,当我尝试更改一个嵌套字典的值时,它会更改其他嵌套字典中的值。
代码:
testing_servers = [912361242985918464, 938245167880753202]
server_ids = {}
default_server_vals = {'beetle_game_started': False, 'beetle_message_id': None,
'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list' : [], "player2_list":[]}
@bot.event
async def on_ready():
print('logged in')
for i in bot.guilds:
global server_ids
global default_server_vals
server_ids[str(i.id)] = default_server_vals
print(server_ids)
@bot.event
async def on_guild_join(guild):
server_ids[str(guild.id)] = default_server_vals
@bot.slash_command(guild_ids=testing_servers, name="test", description="Test out bot latency")
async def test(ctx):
await ctx.respond(f"Bot Latency: {bot.latency * 100}")
@bot.slash_command(guild_ids=testing_servers, name="eightball", description="Play 8ball with friends")
async def eightball(ctx, question):
eightball_int = random.randint(1, 5)
response = None
if eightball_int == 1:
response = "I don't quite know"
if eightball_int == 2:
response = "Well no."
if eightball_int == 3:
response = "Yes of course!"
if eightball_int == 4:
response = "Maybe it's best not to answer."
if eightball_int == 5:
response = "Bruh Moment."
embed = discord.Embed(title="Eightball", description=f"""You asked: {question}
My response: {response}""", colour=discord.Colour.green())
await ctx.respond(embed=embed)
@bot.slash_command(guild_ids=testing_servers, name="roll_dice", description="Roll a dice!")
async def roll_dice(ctx, sides: int):
dice_int = random.randint(1, int(sides))
embed = discord.Embed(title="Dice", colour=discord.Colour.green())
embed.add_field(name="You rolled a:", value=str(dice_int))
embed.add_field(name="Dice sides:", value=str(sides))
await ctx.respond(embed=embed)
@bot.slash_command(guild_ids=testing_servers, name="beetle", description="2 Player game")
async def beetle(ctx):
print(server_ids[str(ctx.guild.id)].get('beetle_game_on'), server_ids[str(ctx.guild.id)].get('beetle_game_started'))
if server_ids[str(ctx.guild.id)].get('beetle_game_on') == False and server_ids[str(ctx.guild.id)].get('beetle_game_started') == False:
await ctx.respond("Game starting! React to join.")
game_start_embed = discord.Embed(title="React to join beetle game! (2 Players Only)",
colour=discord.Colour.green())
game_start_embed.add_field(name="GAME RULES", value="""There are two players. There is one dice! The first player to finish the beetle drawing wins.
Rolling a 1 – Body
Rolling a 2 – Head
Rolling a 3 – A leg
Rolling a 4 – An eye
Rolling a 5 – An antenna
Rolling a 6 – The tail
The first player to roll all 6 wins. However, the head and body must be drawn first to draw the other beetle parts.""")
message = await ctx.send(embed=game_start_embed)
await message.add_reaction("")
print(ctx.guild.id)
server_ids[str(ctx.guild.id)]['beetle_game_started'] = True
print(server_ids)
server_ids[str(ctx.guild.id)]['beetle_message_id'] = message.id
server_ids[str(ctx.guild.id)]['beetle_message_channel'] = message.channel
elif server_ids[str(ctx.guild.id)].get('beetle_game_started'):
await ctx.respond("Someone already started a game! Try and join them.")
else:
await ctx.respond("There is already a beetle game playing!")
这在 on_ready 中的作用是获取机器人已经存在的服务器 IDS,并将其放入全局 server_ids 变量中。然后将嵌套字典作为字典的服务器 ID 值。但是,当我尝试编辑嵌套字典的值时(在甲虫斜杠命令内),它会更改所有其他嵌套值。
例如,当我尝试更改 beetle_game_started 的嵌套字典值时,它打印如下:
{'912361242985918464': {'beetle_game_started': True, 'beetle_message_id': None, 'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list': [], 'player2_list': []}, '938245167880753202': {'beetle_game_started': True, 'beetle_message_id': None, 'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list': [], 'player2_list': []}}
它以某种方式改变了服务器 IDS 的两个嵌套字典的值('beetle_game_started' 的值)
如何在不更改其他字典值的情况下更改一个嵌套字典的值?谢谢
您看到此行为的原因是 python 字典是可变对象。
从提供的代码中提取相关部分
default_server_vals = {'beetle_game_started': False, 'beetle_message_id': None,
'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list' : [], "player2_list":[]}
和
server_ids[str(i.id)] = default_server_vals
server_ids[str(i.id)] 赋值只是创建对单个字典的新引用。这就是为什么当您更改一个 ID 的值时,您会观察到所有其他 ID 的更改。
解决此问题的一种方法是制作副本。我建议看看 python 的复制库 https://docs.python.org/3/library/copy.html
由于 default_server_vals 包含列表作为值,您需要考虑 deepcopy
*抱歉,如果标题没有意义,我不确定如何表达它
所以我开始在 Pycord 的库中制作 python discord 机器人。我想制作一个可以在多台服务器上运行的机器人,并且每台服务器都有不同的值。因此,为此,我制作了一个字典,将所有这些值存储在一个嵌套字典中。但是,当我尝试更改一个嵌套字典的值时,它会更改其他嵌套字典中的值。
代码:
testing_servers = [912361242985918464, 938245167880753202]
server_ids = {}
default_server_vals = {'beetle_game_started': False, 'beetle_message_id': None,
'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list' : [], "player2_list":[]}
@bot.event
async def on_ready():
print('logged in')
for i in bot.guilds:
global server_ids
global default_server_vals
server_ids[str(i.id)] = default_server_vals
print(server_ids)
@bot.event
async def on_guild_join(guild):
server_ids[str(guild.id)] = default_server_vals
@bot.slash_command(guild_ids=testing_servers, name="test", description="Test out bot latency")
async def test(ctx):
await ctx.respond(f"Bot Latency: {bot.latency * 100}")
@bot.slash_command(guild_ids=testing_servers, name="eightball", description="Play 8ball with friends")
async def eightball(ctx, question):
eightball_int = random.randint(1, 5)
response = None
if eightball_int == 1:
response = "I don't quite know"
if eightball_int == 2:
response = "Well no."
if eightball_int == 3:
response = "Yes of course!"
if eightball_int == 4:
response = "Maybe it's best not to answer."
if eightball_int == 5:
response = "Bruh Moment."
embed = discord.Embed(title="Eightball", description=f"""You asked: {question}
My response: {response}""", colour=discord.Colour.green())
await ctx.respond(embed=embed)
@bot.slash_command(guild_ids=testing_servers, name="roll_dice", description="Roll a dice!")
async def roll_dice(ctx, sides: int):
dice_int = random.randint(1, int(sides))
embed = discord.Embed(title="Dice", colour=discord.Colour.green())
embed.add_field(name="You rolled a:", value=str(dice_int))
embed.add_field(name="Dice sides:", value=str(sides))
await ctx.respond(embed=embed)
@bot.slash_command(guild_ids=testing_servers, name="beetle", description="2 Player game")
async def beetle(ctx):
print(server_ids[str(ctx.guild.id)].get('beetle_game_on'), server_ids[str(ctx.guild.id)].get('beetle_game_started'))
if server_ids[str(ctx.guild.id)].get('beetle_game_on') == False and server_ids[str(ctx.guild.id)].get('beetle_game_started') == False:
await ctx.respond("Game starting! React to join.")
game_start_embed = discord.Embed(title="React to join beetle game! (2 Players Only)",
colour=discord.Colour.green())
game_start_embed.add_field(name="GAME RULES", value="""There are two players. There is one dice! The first player to finish the beetle drawing wins.
Rolling a 1 – Body
Rolling a 2 – Head
Rolling a 3 – A leg
Rolling a 4 – An eye
Rolling a 5 – An antenna
Rolling a 6 – The tail
The first player to roll all 6 wins. However, the head and body must be drawn first to draw the other beetle parts.""")
message = await ctx.send(embed=game_start_embed)
await message.add_reaction("")
print(ctx.guild.id)
server_ids[str(ctx.guild.id)]['beetle_game_started'] = True
print(server_ids)
server_ids[str(ctx.guild.id)]['beetle_message_id'] = message.id
server_ids[str(ctx.guild.id)]['beetle_message_channel'] = message.channel
elif server_ids[str(ctx.guild.id)].get('beetle_game_started'):
await ctx.respond("Someone already started a game! Try and join them.")
else:
await ctx.respond("There is already a beetle game playing!")
这在 on_ready 中的作用是获取机器人已经存在的服务器 IDS,并将其放入全局 server_ids 变量中。然后将嵌套字典作为字典的服务器 ID 值。但是,当我尝试编辑嵌套字典的值时(在甲虫斜杠命令内),它会更改所有其他嵌套值。
例如,当我尝试更改 beetle_game_started 的嵌套字典值时,它打印如下:
{'912361242985918464': {'beetle_game_started': True, 'beetle_message_id': None, 'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list': [], 'player2_list': []}, '938245167880753202': {'beetle_game_started': True, 'beetle_message_id': None, 'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list': [], 'player2_list': []}}
它以某种方式改变了服务器 IDS 的两个嵌套字典的值('beetle_game_started' 的值) 如何在不更改其他字典值的情况下更改一个嵌套字典的值?谢谢
您看到此行为的原因是 python 字典是可变对象。
从提供的代码中提取相关部分
default_server_vals = {'beetle_game_started': False, 'beetle_message_id': None,
'beetle_message_channel': None, 'beetle_player_1': None, 'beetle_player_2': None, 'beetle_game_on': False, 'player1_list' : [], "player2_list":[]}
和
server_ids[str(i.id)] = default_server_vals
server_ids[str(i.id)] 赋值只是创建对单个字典的新引用。这就是为什么当您更改一个 ID 的值时,您会观察到所有其他 ID 的更改。
解决此问题的一种方法是制作副本。我建议看看 python 的复制库 https://docs.python.org/3/library/copy.html
由于 default_server_vals 包含列表作为值,您需要考虑 deepcopy