Python:for索引分配中的循环

Python:for索引分配中的循环,python,dictionary,indexing,variable-assignment,Python,Dictionary,Indexing,Variable Assignment,在阅读托比·塞加兰(Toby Segaran)的著作《编程集体智慧》(Programming Collective Intelligence)的过程中,我遇到了一些我并不完全熟悉的索引分配技巧 以此为例: createkey='_'.join(sorted([str(wi) for wi in wordids])) 或: 索引中的所有嵌套元组让我有点困惑。这些变量实际分配了什么?我显然假设.join一个作为字符串出现,但是后者呢?如果有人能解释这些循环的机制,我会非常感激。我认为这些都是非常常

在阅读托比·塞加兰(Toby Segaran)的著作《编程集体智慧》(Programming Collective Intelligence)的过程中,我遇到了一些我并不完全熟悉的索引分配技巧

以此为例:

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


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

后者相当于:

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

for wi in wordids:
  myList.append(str(wi))
这将通过迭代
linkscores.items()
中的元组,并为每个元组计算
(u,float(l)/maxscore)
来创建一个列表

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

作为从元组列表创建dict的另一个示例:

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

让我们看第一个:

  • wordids中wi的str(wi)获取wordids中的每个元素并将其转换为字符串
  • 排序(…)
    对它们进行排序(按字典顺序)
  • join(…)将已排序的单词ID合并为单个字符串,并在条目之间加下划线
  • 现在是第二个:

    normalizedscores = dict([(u,float(1)/maxscore) for (u,l) in linkscores.items()])
    
  • linkscores
    是一个字典(或类似字典的对象)
  • linkscores.items()中(u,l)的
    迭代字典中的所有条目,为每个条目分配键和值给
    u
    l
  • (u,float(1)/maxscore)
    是一个元组,其中第一个元素是
    u
    ,第二个元素是
    1/maxscore
    (对我来说,这看起来可能是一个打字错误:
    float(l)/maxscore
    更有意义——请注意小写字母el代替一个)
  • dict(…)
    从元组列表构造一个字典,其中每个元组的第一个元素作为键,第二个元素作为值
  • 简而言之,它复制字典,保留键并将每个值除以
    maxscore

    [str(wi) for wi in wordids]
    
    是一个

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

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

    wordids
    中的每个项目创建一个字符串列表,然后对该列表进行排序,并使用
    \uu
    作为分隔符将其合并为一个大字符串

    正如agf正确指出的,您还可以使用生成器表达式,它看起来就像一个列表,但使用括号而不是括号。如果您以后不需要列表,这可以避免构建列表(迭代列表除外)。如果你已经有了括号,比如在这个例子中,
    sorted(…)
    你可以简单地删除括号

    但是,在这种特殊情况下,您不会获得性能优势(事实上,它会慢10%左右;我对它进行了计时),因为
    sorted()
    无论如何都需要构建一个列表,但它看起来更好一些:

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

    遍历字典
    linkscores
    中的项,其中每个项都是一个键/值对。它创建一个key/
    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
    
    >>> 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
    
    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)]")
    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
    
    >>> 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
    

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

    >>> 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循环遍历列表,对列表进行排序,然后将所有已排序的值合并成一个字符串,用“u”

    分隔值在
    []
    括号内发生的奇怪业务称为列表理解,它基本上是构建列表的一种非常简洁的方法
    myList=[str(wi)表示wordid中的wi]
    相当于:

    normalizedscores = {}
    for u, l in linkscores.items():
        normalizedscores[u] = float(l) / maxscore
    
    myList = []
    
    for wi in wordids:
      myList.append(str(wi))
    
    sorted()
    然后对该列表进行排序,
    join()
    给出一个字符串,其中列表项用下划线分隔,如下所示:
    item1\u item2\u item3…

    第二个作业更复杂/简洁,但下面是发生的情况:

    • linkscores
      看起来像一个字典,而
      items()
      方法从字典中返回
      (键,值)
      元组的列表。因此linkscores.items()中(u,l)的
      正在该列表上循环
      
    • 对于每个元组,我们创建一个包含
      (u,float(l)/maxscore)
      的新元组,并将其添加到列表中。因此,这一步基本上将
      (项,值)
      列表更改为
      (项,规范化值)
      元组列表
    • dict()
      函数将其转换回字典

    这样做的总体结果是获取dict中的所有值并对其进行规范化。也许有一种更简单/更详细的方法可以做到这一点,但这种方法的好处是看起来很酷。我不喜欢用列表理解来做一些疯狂的事情,因为这会损害可读性,所以如果你自己不想写这种东西,也不要觉得很糟糕

    @andronikus没有。Python 2.7。我认为作者在撰写本文时可能使用了较旧版本的Python,因为我从他的博客下载了修订后的示例代码,在那里他使用了您描述的字典理解方法。哦,我真该死:。反对撤回@我已经把我的答案说得更清楚了,谢谢。毕竟,Python2.5和2.6仍然被广泛使用……是的,我想我仍然使用其中的一种。到目前为止,我从未听说过听写理解,这对我没有帮助。很酷+2如果你解释一下列表comp的基本功能(我感觉OP没有意识到,但我可能错了),那么每个人都提到了列表理解。人们没有提到的是那些例子