猿问

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

我一直在考虑将我的 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

是的,我可能一个人在这里犯下各种风格指南的罪过。我是自学的,发现这个项目的所有好的实践都太晚了。对不起,如果我让你的眼睛流血了。


慕丝7291255
浏览 169回答 2
2回答

慕森卡

我建议创建一个需要删除的键列表,然后在完成循环后删除它们:def Age(beats):&nbsp; &nbsp; to_remove = []&nbsp; &nbsp; actions = []&nbsp; &nbsp; for echo in echoes.keys():&nbsp; &nbsp; &nbsp; &nbsp; echoes[echo]['elapsed'] += beats&nbsp; &nbsp; &nbsp; &nbsp; activations = echoes[echo]['elapsed']/echoes[echo]['interval']&nbsp; &nbsp; &nbsp; &nbsp; while activations >= 1 :&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions.append(str(echoes[echo]['action']))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; echoes[echo]['elapsed'] -= echoes[echo]['interval']&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; activations = echoes[echo]['elapsed']/echoes[echo]['interval']&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try :&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; echoes[echo]['reps'] -= 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if echoes[echo]['reps'] < 1 :&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; to_remove.append(echo)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except TypeError : #Will be raised if reps is Infinite&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass&nbsp; &nbsp; for echo in to_remove:&nbsp; &nbsp; &nbsp; &nbsp; del echoes[echo]&nbsp; &nbsp; char['Echoes'] = echoes&nbsp; &nbsp; char.write()&nbsp; &nbsp; return actions我也认为它的可读性稍微好一些.items():for echo, value in echoes.items():&nbsp; &nbsp; value['elapsed'] += beats&nbsp; &nbsp; ...

MMMHUHU

我已经看到 d.copy().keys() 建议,但我不明白为什么 (Python 3) .keys() 位是必要的。你读得还不够仔细。由于d.copy().keys()创建了字典的副本然后从该副本创建键,因此它本质上指向字典和键的新“视图”。这基本上是它在 python 2.7 中所做的,因此它可以用于您的目的。因此,在 python 2.7 中,直接从 dict 创建一个新列表并返回,而 python 3 直接指向该 dict 的键,这意味着如果它在迭代过程中发生变化,它将抛出并出错。您可以在 python 3 中解决此问题的另一种方法是:for&nbsp;x&nbsp;in&nbsp;list(d):因为这将返回一个在迭代过程中不会改变大小的“新”列表。
随时随地看视频慕课网APP

相关分类

Python
我要回答