这个return语句的含义是什么?Python

4

我正在研究遗传算法,找到了一段可行的代码,现在正努力理解其中的细节。但是我看到了这个return语句:

return sum(1 for expected, actual in zip(target, guess)
  if expected == actual)

它是做什么的?

以下是完整代码:

main.py:

from population import *

while True:
    child = mutate(bestParent)
    childFitness = get_fitness(child)
    if bestFitness >= childFitness:
        continue
    print(child)
    if childFitness >= len(bestParent):
        break
    bestFitness = childFitness
    bestParent = child

population.py:

import random

geneSet = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!.,1234567890-_=+!@#$%^&*():'[]\""
target = input()

def generate_parent(length):
    genes = []
    while len(genes) < length:
        sampleSize = min(length - len(genes), len(geneSet))
        genes.extend(random.sample(geneSet, sampleSize))
    parent = ""
    for i in genes:
        parent += i
    return parent

def get_fitness(guess):
    return sum(1 for expected, actual in zip(target, guess)
        if expected == actual)

def mutate(parent):
    index = random.randrange(0, len(parent))
    childGenes = list(parent)
    newGene, alternate = random.sample(geneSet, 2)
    childGenes[index] = alternate \
        if newGene == childGenes[index] \
        else newGene

    child = ""
    for i in childGenes:
        child += i

    return child

def display(guess):
    timeDiff = datetime.datetime.now() - startTime
    fitness = get_fitness(guess)
    print(str(guess) + "\t" + str(fitness) + "\t" + str(timeDiff))

random.seed()
bestParent = generate_parent(len(target))
bestFitness = get_fitness(bestParent)
print(bestParent)

这是一个可运行的遗传算法完整代码,我修改了一些部分以使其更易读。

返回语句在population.py文件中的get_fitness函数中。


3
“列表推导式”是什么意思?它如何工作?我该如何使用它? - vaultah
它被称为列表推导式。如果您发布更多的代码,将会有所帮助。 - whackamadoodle3000
@vaultah,那是一个生成器表达式而不是列表推导式。尽管如此,您提供的链接确实提供了有关推导式的一般解释,因此我也会投票关闭重复内容。 - Christian Dean
@ChristianDean:这是针对同时解释推导式和生成器表达式的问题的规范重复。尽管如此,我没有投票将其关闭为重复。 - vaultah
@vaultah 哦,我现在明白了。我没有向下滚动足够远以查看规范答案。愚蠢的瞬间。对此感到抱歉。无论如何,既然它是规范的重复目标,更有理由将其关闭为重复项。 - Christian Dean
4个回答

5

让我们来分解一下:

return sum(1 for expected, actual in zip(target, guess)
  if expected == actual)

可以写成:

total = 0
for i in range(len(target)):
    if target[i] == guess[i]:
        total = total + 1
return total

zip(a, b)函数可以将两个列表 ab 中的元素一一对应组成一个新的列表,例如:

zip([1, 2, 3], ['a', 'b', 'c'])

产生了[(1, 'a'), (2, 'b'), (3, 'c')]的结果。因此,zip(target, guess)表达式返回了一个列表,其中包含从targetguess中提取的第一个项目,然后是从targetguess中提取的第二个项目,以此类推。 for expected, actual in zip()部分从zip()的输出中“解压”出值对,因此第一对(来自target)进入变量expected,第二对(来自guess)进入变量actual1 ... if expected == actual部分表示“如果expected中的值等于actual中的值,则对zip()中的每个项目发出1的值”。 sum()将for循环中的1值相加。
哇!现在您可以统计预期值和实际值相同的项目数了。以下是编写该代码的几个原因:
  1. 它非常简洁但表达清晰。经常编写Python代码的人可以看一眼就明白。
  2. 它可能非常快,因为Python解释器处理循环、条件语句等,而Python解释器的改进可以使代码更快,而不必理解整个程序。基本上,您告诉Python“我想做这件事”,而不是“这里有100个小步骤来完成这件事”。

非常感谢您。我现在明白了。这正是我所需要的。再次感谢您。 - user8467049
我很乐意帮忙! - Kirk Strauser

1
我认为它返回实际值等于预期值的匹配总数。本质上,我认为它是在检查算法模型能够正确预测的次数。

是的,它返回了什么,但这些都是什么?我不理解这个语法。 - user8467049
你不明白这个语法在做什么吗?只是想了解你想知道什么。 - Ajwadd Anwarr

1

这是一种使用zip()函数的列表推导式List Comprehension

基本上,代码的意思是:

  • 创建一个列表。
  • 从zip(target, guess)中检索变量“expected”和“actual”。如果它们相等,则将1添加到列表中。
  • 重复以上步骤,直到从zip(target, guess)中获取所有值。
  • 对所有1进行求和。
  • 返回这个总和。

1

有几件事情正在进行:

return sum(...)

这意味着你返回了一个数字。

sum 的内部部分是一个 生成器表达式,它创建并运行一个隐式循环。

在这种情况下,1 for expected, actual in zip(target, guess) if expected == actual 创建了一个 1 值的序列,每当保护条件为真时(expected == actual)就创建一个条目。

因此,这一行实际上创建了像这样的代码:sum(1, 1, 1, 1, ...)

在生成器表达式中,你有一个 zip 调用。zip 表达式将两个(或更多!)序列转换为一个带有两个(或更多!)值的单个序列。也就是说,zip(['a', 'b', 'c'], [1, 2, 3]) 将产生如下所示的序列:[('a', 1), ('b', 2), ('c', 3)]

所以,如果您的期望结果[1, 2, 3],而实际结果[1, 1, 3],您将获得以下zip结果:
expected = [1, 2, 3]
actual = [1, 1, 3]
zip(expected, actual)   # [(1, 1), (2, 1), (3, 3)]

生成器表达式包含一个 for,它使用曾经被称为“元组解包”的方式,将单个聚合(元组)值中的多个目标分配给其 target_list
因此,当 zip 表达式生成 (1, 1) 时,for expected, actual 将其解包为 expected=1, actual=1
因此,zip函数接受两个长度相等的序列,并将它们对应的元素配对:a[0]与b[0],a[1]与b[1],以此类推。for生成器表达式将这些元素赋值给名为expectedactual的变量。for...if生成器条件部分比较expected == actual的值,并生成或不生成值。因此,生成的序列长度保证小于或等于输入序列的长度,但你不知道它有多长。生成器的expression部分只是1。所以你有一个长度可变的1序列。它不是1或0。它是1或无条目。将所有的1加起来,那就是结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接