Python: 在索引赋值中使用for循环

4 投票
6 回答
10638 浏览
提问于 2025-04-17 04:19

在阅读托比·塞加兰的《编程集体智能》这本很棒的书时,我遇到了一些关于索引赋值的技巧,我不是很熟悉。

比如说这个:

createkey='_'.join(sorted([str(wi) for wi in wordids]))

或者:

normalizedscores = dict([(u,float(l)/maxscore) for (u,l) in linkscores.items()])

这些嵌套的元组让我有点困惑。其实这些变量被赋值的是什么呢?我当然知道 .join 的结果是一个字符串,但后面的那个呢?如果有人能解释一下这些循环的原理,我会非常感激。我觉得这些技巧应该是比较常见的,但作为一个Python新手,问这个问题可能有点不好意思。谢谢!

6 个回答

1

后者等同于:

normalizedscores = {}
for u, l in linkscores.items():
    normalizedscores[u] = float(l) / maxscore
3

我们先来看第一个:

  1. str(wi) for wi in wordids 是把 wordids 里的每一个元素都转成字符串。
  2. sorted(...) 是把这些字符串按字母顺序排列。
  3. '_'.join(...) 是把排好序的字符串用下划线连接成一个长字符串。

现在来看第二个:

normalizedscores = dict([(u,float(1)/maxscore) for (u,l) in linkscores.items()])
  1. linkscores 是一个字典(或者说类似字典的东西)。
  2. for (u,l) in linkscores.items() 是在遍历字典里的每一项,把每一项的键和值分别赋给 ul
  3. (u,float(1)/maxscore) 是一个元组,第一个元素是 u,第二个元素是 1/maxscore(我觉得这里可能有个小错误:用 float(l)/maxscore 会更合理——注意这里的字母是小写的 l,而不是数字一)。
  4. dict(...) 是从这些元组里创建一个新的字典,元组的第一个元素作为键,第二个元素作为值。

简单来说,这段代码是复制了这个字典,保留了键,并把每个值都除以 maxscore

15
[str(wi) for wi in wordids]

这是一个列表推导式

a = [str(wi) for wi in wordids]

这和下面的内容是一样的

a = []
for wi in wordids:
    a.append(str(wi))

所以

createkey='_'.join(sorted([str(wi) for wi in wordids]))

这个代码从wordids中的每个项目创建一个字符串列表,然后对这个列表进行排序,并用_作为分隔符把它们连接成一个大字符串。

正如agf正确指出的,你也可以使用生成器表达式,它看起来和列表推导式很像,只不过用的是圆括号而不是方括号。如果你后面不需要这个列表(除了遍历它),这样做可以避免创建一个列表。而且如果你已经有了圆括号,比如在sorted(...)的情况下,你可以直接去掉方括号。

不过,在这个特殊情况下,你不会获得性能上的好处(实际上,它会慢大约10%;我测过了),因为sorted()无论如何都需要构建一个列表,但这样看起来会更好一些:

createkey='_'.join(sorted(str(wi) for wi in wordids))

normalizedscores = dict([(u,float(l)/maxscore) for (u,l) in linkscores.items()])

这个代码遍历字典linkscores中的每个项目,每个项目都是一个键/值对。它创建一个键和l/maxscore的元组列表,然后把这个列表再转回字典。

不过,从Python 2.7开始,你也可以使用字典推导式

normalizedscores = {u:float(l)/maxscore for (u,l) in linkscores.items()}

这里有一些时间数据:

Python 3.2.2

>>> import timeit
>>> timeit.timeit(stmt="a = '_'.join(sorted([str(x) for x in n]))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
61.37724242267409
>>> timeit.timeit(stmt="a = '_'.join(sorted(str(x) for x in n))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
66.01814811313774

Python 2.7.2

>>> import timeit
>>> timeit.timeit(stmt="a = '_'.join(sorted([str(x) for x in n]))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
58.01728623923137
>>> timeit.timeit(stmt="a = '_'.join(sorted(str(x) for x in n))", setup="import random; n = [random.randint(0,1000) for i in range(100)]")
60.58927580777687

撰写回答