为了账号安全,请及时绑定邮箱和手机立即绑定

Python 3 中 .keys() 的大多数 Pythonic 替换

Python 3 中 .keys() 的大多数 Pythonic 替换

慕丝7291255 2021-06-04 16:53:48
我一直在考虑将我的 Python 2.7 项目转换为 3。我发现我主要使用 .keys() 作为不必要的for x in d:具有相同的效果for in in d.keys():但是,我还了解到,在遍历字典时,您不应该对其进行变异。这还没有出现,因为我一直在使用 Python2.7 的 .keys() 来创建字典键的副本作为列表。Python 3 的 .keys() 版本创建的是视图而不是副本,因此不能用于相同目的。2to3 将 d.keys() 转换为 list(d.items()) 但我并不严格需要列表中的键。我已经看到 d.copy().keys() 建议,但我不明白为什么 (Python 3) .keys() 位是必要的。在 Python Docs 中它说在迭代字典时修改键的值是安全的,但前提是键集不改变那么“变异”是否仅指更改密钥呢?大多数情况下,我只在迭代时更改字典值,但我发现某个地方有可能删除当前键所以基本上我需要用任何东西替换 .keys() ,如果是这样,最pythonic/高效的选项是什么?具体代码(我在冒险游戏/互动小说引擎中重复效果/随时间推移造成的伤害的一部分)是这样的:def Age(beats) :    actions = []    for echo in echoes.keys() :        echoes[echo]['elapsed'] += beats        activations = echoes[echo]['elapsed']/echoes[echo]['interval']        while activations >= 1 :            actions.append(str(echoes[echo]['action']))            echoes[echo]['elapsed'] -= echoes[echo]['interval']            activations = echoes[echo]['elapsed']/echoes[echo]['interval']            try :                echoes[echo]['reps'] -= 1                if echoes[echo]['reps'] < 1 :                    del echoes[echo]                    break            except TypeError : #Will be raised if reps is Infinite                pass    char['Echoes'] = echoes    char.write()    return actions是的,我可能一个人在这里犯下各种风格指南的罪过。我是自学的,发现这个项目的所有好的实践都太晚了。对不起,如果我让你的眼睛流血了。
查看完整描述

2 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

我建议创建一个需要删除的键列表,然后在完成循环后删除它们:


def Age(beats):

    to_remove = []

    actions = []

    for echo in echoes.keys():

        echoes[echo]['elapsed'] += beats

        activations = echoes[echo]['elapsed']/echoes[echo]['interval']

        while activations >= 1 :

            actions.append(str(echoes[echo]['action']))

            echoes[echo]['elapsed'] -= echoes[echo]['interval']

            activations = echoes[echo]['elapsed']/echoes[echo]['interval']

            try :

                echoes[echo]['reps'] -= 1

                if echoes[echo]['reps'] < 1 :

                    to_remove.append(echo)

                    break

            except TypeError : #Will be raised if reps is Infinite

                pass

    for echo in to_remove:

        del echoes[echo]

    char['Echoes'] = echoes

    char.write()

    return actions

我也认为它的可读性稍微好一些.items():


for echo, value in echoes.items():

    value['elapsed'] += beats

    ...


查看完整回答
反对 回复 2021-06-16
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

我已经看到 d.copy().keys() 建议,但我不明白为什么 (Python 3) .keys() 位是必要的。

你读得还不够仔细。由于d.copy().keys()创建了字典的副本然后从该副本创建键,因此它本质上指向字典和键的新“视图”。

这基本上是它在 python 2.7 中所做的,因此它可以用于您的目的。

因此,在 python 2.7 中,直接从 dict 创建一个新列表并返回,而 python 3 直接指向该 dict 的键,这意味着如果它在迭代过程中发生变化,它将抛出并出错。

您可以在 python 3 中解决此问题的另一种方法是:

for x in list(d):

因为这将返回一个在迭代过程中不会改变大小的“新”列表。


查看完整回答
反对 回复 2021-06-16
  • 2 回答
  • 0 关注
  • 168 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信