【问题标题】:Why does python's dictionary iteration seemingly work with a copy?为什么 python 的字典迭代似乎与副本一起工作?
【发布时间】:2011-08-10 19:35:58
【问题描述】:

我很困惑 python 是如何遍历这本字典的。在 python 的文档中,itervalues 返回字典值的迭代器。

dict = {"hello" : "wonderful", "today is" : "sunny", "more text" : "is always good"}

for x in dict.itervalues():
    x = x[2:]   

print dict

这将打印出原始字典不变。这是为什么?如果我说位置 x 的值是“blabla”,为什么它没有被设置?

【问题讨论】:

  • +1 表示好问题。它让我一秒钟。

标签: python iterator copy items


【解决方案1】:

这与字符串或列表无关。问题在于for 的展开方式。

在做

for x in d.iteritems():
    # loop body

或多或少等同于做

iter = d.itervalues()
while True:
    try:
        x = next(iter)
        # loop body
    except StopIteration:
        break

因此,考虑到这一点,不难看出我们只是重新分配了x,它保存了函数调用的结果。

iter = d.itervalues()
while True:
    try:
        x = next(iter)

        x = 5 # There is nothing in this line about changing the values of d
    except StopIteration:
        break

【讨论】:

  • 谢谢,这已经为我澄清了。我希望 python 文档能更详细地解释一些事情,例如 for 语句的复杂性和各种方法。
【解决方案2】:

唯一的一行

x = x[2:]

确实是创建字符串切片x[2:] 并重新绑定名称x 以指向这个新字符串。它不会更改之前指向的字符串x。 (字符串在 Python 中是不可变的,不能更改。)

要实现你真正想要的,你需要让字典入口指向切片创建的新字符串对象:

for k, v in my_dict.iteritems():
    my_dict[k] = v[2:] 

【讨论】:

  • 这与字符串不可变无关;如果我用"hello":[1,2] 替换"hello":"wonderful",它的工作原理是一样的。
  • @Mark:我还给出了这种行为的真正原因——字符串不可变这一事实只是一个旁注。但它确实会影响解决方案 - 如果值是列表,您可以使用 for x in my_dict: del x[:2] 来实现所需的行为。
  • @Emil:我不明白你的评论。它与我的答案有什么关系吗?还是对我的评论?这是你的反对票吗?
  • @Sven:对不起,再读几遍后,它实际上是正确的。
【解决方案3】:

正如Sven Marnach 指出的那样,字符串是不可变的,您只是将x 重新绑定到由切片表示法创建的新字符串。您可以使用id 证明x 确实 指向字典中的同一个对象:

>>> obj = 'hello'

>>> id(obj)
<<< 4318531232

>>> d = {'key': obj}   

>>> [id(v) for v in d.values()]
<<< [4318531232]

>>> [id(v) for v in d.itervalues()]
<<< [4318531232]

>>> [(k, id(v)) for k, v in d.items()]
<<< [('key', 4318531232)]

>>> [(k, id(v)) for k, v in d.iteritems()]
<<< [('key', 4318531232)]

您可以使用iteritems 一起迭代键和值以执行您想要的操作:

for k,v in dict.iteritems():
    dict[k] = v[2:]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    相关资源
    最近更新 更多