【问题标题】:Python: for loop in index assignmentPython:索引分配中的for循环
【发布时间】:2011-12-07 19:19:49
【问题描述】:

在阅读 Toby Segaran 的精彩书籍“Programming Collective Intelligence”时,我遇到了一些我并不完全熟悉的索引分配技术。

以此为例:

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

或:

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

索引中的所有嵌套元组让我有点困惑。实际上分配给这些变量的是什么?我显然假设.join 是一个字符串,但是后者呢?如果有人能解释这些循环的机制,我会非常感激。我认为这些是非常常见的技术,但是对于 Python 来说是新手,我想问一下有点遗憾。谢谢!

【问题讨论】:

  • 每个人都提到这些是列表推导。人们没有提到的是那些例子是错误的并且那些方括号应该被省略——它们应该是生成器表达式,它们是相同的,只是它们只根据需要产生值,而不是将它们全部存储在一个列表中。由于您只是立即使用列表然后将它们丢弃,因此最好只使用生成器表达式。
  • @agf 你能举个例子吗?我是这种方法的新手。谢谢!
  • 只需用括号替换方括号,sorteddict 函数将一次要求一个值,生成器表达式将给出该值,而不是将它们全部存储在临时列表。
  • sorted() 不建立一个列表吗?
  • @agf:我刚刚计时了,sorted() 在生成器表达式上比在列表上花费的时间大约长 10%。

标签: python dictionary indexing variable-assignment


【解决方案1】:
[str(wi) for wi in wordids]

是一个list comprehension

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 的项目,其中每个项目是一个键/值对。它创建一个 key/l/maxscore 元组列表,然后将该列表转换回字典。

但是,从 Python 2.7 开始,您也可以使用 dict comprehensions

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

【讨论】:

  • @andronikus 不。 Python 2.7。
  • 我认为作者在撰写本文时可能使用的是旧版本的 python,因为我从他的博客下载了修改后的示例代码,并且在那里他使用了您描述的字典理解方法。跨度>
  • 哦,我该死:docs.python.org/dev/whatsnew/2.7.html#python-3-1-features。反对撤回!
  • @andronikus:我的回答更清楚了,谢谢。毕竟 Python 2.5 和 2.6 仍然被广泛使用...
  • 是的,我想我仍然使用其中之一。直到现在我才听说过 dict 理解,这无济于事。很酷!
【解决方案2】:

让我们采取第一个:

  1. str(wi) for wi in wordids 获取wordids 中的每个元素并将其转换为字符串。
  2. sorted(...) 对它们进行排序(按字典顺序)。
  3. '_'.join(...) 将排序后的单词 id 合并为单个字符串,条目之间使用下划线。

现在是第二个:

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 会更有意义——注意小写字母el 代替一个)。
  4. dict(...) 从元组列表中构造一个字典,其中每个元组的第一个元素作为键,第二个元素作为值。

简而言之,它会复制字典,保留键并将每个值除以maxscore

【讨论】:

  • +2 如果您解释列表组合的基本作用(我感觉 OP 没有意识到这一点,但我可能错了)
【解决方案3】:

后者相当于:

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

【讨论】:

    【解决方案4】:
    [(u,float(1)/maxscore) for (u,l) in linkscores.items()]
    

    这通过迭代linkscores.items() 中的元组并为每个元组计算(u, float(l)/maxscore) 来创建一个列表。

    dict([this list])
    

    linkscores 中的每个项目创建一个dict,其中包含列表理解结果中的条目-(u, float(l)/maxscore)

    另一个从元组列表创建字典的例子:

    >>> l = [(1,2), (3,4), (5,6)]
    >>> d = dict(l)
    >>> d
    {1: 2, 3: 4, 5: 6}
    

    【讨论】:

      【解决方案5】:

      这里是第一个例子……例子

      >>> wordids = [1,2,4,3,10,7]
      >>> createkey='_'.join(sorted([str(wi) for wi in wordids]))
      >>> print createkey
      1_10_2_3_4_7
      

      它所做的是用for循环遍历列表,对列表进行排序,然后将所有排序的值连接成一个字符串,用'_'分隔值

      【讨论】:

        【解决方案6】:

        [] 括号内发生的看起来很奇怪的事情称为列表推导,它基本上是一种非常简洁的构建列表的方式。 myList = [str(wi) for wi in wordids] 相当于:

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

        sorted() 然后对该列表进行排序,join() 给出一个字符串,这些列表项之间用下划线分隔,例如:item1_item2_item3_...

        第二个任务更复杂/简洁,但这是发生了什么:

        • linkscores 看起来像一个字典,items() 方法从字典中返回一个 (key, value) 元组列表。所以for (u,l) in linkscores.items() 正在遍历该列表。
        • 对于每个元组,我们创建一个包含(u, float(l)/maxscore) 的新元组,并将其添加到列表中。所以这一步基本上将您的(item, value) 列表更改为(item, normalized value) 元组列表。
        • dict() 函数将其转换为字典。

        这样做的总体结果是获取 dict 中的所有值并对其进行规范化。可能有一种更简单/更冗长的方式来做到这一点,但这种方式的好处是看起来很酷。我不喜欢用列表推导做一些疯狂的事情,因为它会损害可读性,所以如果你不想自己写这种东西,一点也不难过!

        【讨论】:

          猜你喜欢
          • 2020-09-09
          • 1970-01-01
          • 1970-01-01
          • 2013-06-11
          • 2018-03-16
          • 1970-01-01
          • 2013-03-20
          • 2015-08-10
          • 2021-07-08
          相关资源
          最近更新 更多