【问题标题】:Why does "in" work for keys but not for strings?为什么“in”适用于键而不适用于字符串?
【发布时间】:2019-03-06 21:45:05
【问题描述】:

我今天在 Python 中遇到了一个非常奇怪的关于字符串和字典的东西。有人可以向我解释为什么 print 语句在第一个 for 循环中有效,但在第二个 for 循环中失败?

test = 'ab'
test_dict = {}
test_dict[test] = 1

for x, y in test_dict:
    print('%s %s' % (x,y))

for x,y in test:
    print('%s %s' % (x,y))

【问题讨论】:

  • 什么是完整的回溯?
  • 第一个打印语句打印出:“a b” 第二个打印语句是错误的,正如预期的那样。
  • 你认为 y 在字符串大小写中应该打印什么?
  • test 是字符串变量而不是字典
  • "字典是键值对的集合。在这种情况下,x,y 持有 x 中的键和 y 中的值" 不正确,请参阅前面的评论。

标签: python string dictionary iterable-unpacking


【解决方案1】:

两个循环都被破坏了。第一个循环碰巧起作用,因为test 正好是两个字符长,因此可以解压缩。分成两个变量xy

要遍历字典的键和值,请编写:

for k,v in d.items():
    ...

如果你只想要钥匙,你可以这样做:

for k in d:
    ...

详细地说,当您遍历一个 dict 时,它会遍历键。

for x,y in test_dict

字典只有一个键,"ab"。因此,在第一次也是唯一一次迭代中,它将该字符串分配给 xy,就像你写的一样:

x,y = "ab"

事实上,这是一个有效的解包。左边是两个变量,右边是一个包含两个项目的容器。 x 变为 "a"y 变为 "b"

如果test 更长或更短,第一个循环也会因“需要多于 N 个值才能解压”或“太多值无法解压”而崩溃。

为什么字符串在一种情况下解包,而在另一种情况下没有解包?

第二个循环直接遍历字符串"ab"。当您遍历一个字符串时,它会将字符串分解为单字符字符串。第一次迭代是"a",第二次是"b"。在第一次迭代中,它尝试做:

x,y = "a"

此赋值失败,“需要多于 1 个值才能解压”,因为左侧有两个变量,右侧只有一个字符。

【讨论】:

  • 我不一定会说“破碎”;如果您知道键是两个字符的字符串,则第一个循环很好。但它确实依赖于那个非常具体的假设。
【解决方案2】:

对于字典的情况,您正在迭代字典键。 for x, y in test_dict 的意思是“对于test_dict 中的每个键,获取键并解压缩到变量xy”。由于唯一的键是'ab',因此字符串被解压缩为x = 'a'y = 'b'。当然,这特别有效,因为您唯一的字符串键的长度为 2。

对于字符串情况,您正在迭代一个字符串。 for x, y in test 将失败。你不能说“为test 中的每个字符解包到多个变量”,因为单个字符是不可迭代的。相反,你会遇到:

ValueError: not enough values to unpack (expected 2, got 1)

【讨论】:

  • 为什么 string 在 1 个场景中解包,而在另一个场景中没有被解包?
  • @J.Mcclane,因为一个是迭代字典键(唯一的键是可迭代的),另一个是迭代字符串(字符串中的字符不可迭代)。我已经更新以进一步澄清。
  • 在第二种情况下,您尝试解压缩单字符串“a”。 (for c in "ab" 取"a" 然后是"b",两者都不能解包到xy
【解决方案3】:
for x,y in test:
  print('%s %s' % (x,y))

由于test 是一个类似列表的对象(python 中的字符串是类似列表的),因此迭代它会依次获取每个字符。字符不是长度为 2 的类似列表的对象,因此尝试将其拆分为 xy 会产生错误。 如果您有test = ("ab", "bc"),那么 test 将是一个包含字符对的元组,可以使用上面的表达式进行拆分。 这是一个非常简短的答案,但我希望它能澄清发生了什么。

这在 dict 案例中起作用的原因有点复杂,但不是很复杂。当你在 python 中迭代一个 dict 时,你实际上是在迭代它的键。这意味着您有一个包含一个项目的列表,它是一个长度为 2 的字符串。正如您在上面看到的,一个长度为 2 的字符串可以解压缩为它的第一个和第二个字符,这就是该语句起作用的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多