简体   繁体   中英

What does this return statement mean? Python

I am working on a genetic algorithm, and I found a code that works, and now I am trying to understand, but I saw this return statement:

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

What does it do?

Here is the full code:

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)

This is the full code of an working genetic algorithm. I modified some parts to make it more readable for me.

The return statement is in the population.py file, in the get_fitness function.

Let's break that down:

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

could be written as:

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

zip(a, b) makes a list of pairs of items from a and b , like:

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

yields [(1, 'a'), (2, 'b'), (3, 'c')] . So the zip(target, guess) expression returns a list of the first item from target and the first item of guess , then the second item from target and the second from guess , and so on.

The for expected, actual in zip() bit unpacks the pairs of values from the output of zip() , so the first of the pair (from target ) goes to the variable expected , and the second of the pair (from guess ) goes to the variable actual .

The 1 ... if expected == actual bit says "emit a value of 1 for every item from zip() if the value in expected equals the value in actual .

sum() adds up the number of 1 values from the for loop.

Ta-da! Now you have the count of items where the expected and actual values are the same. There are a couple of reasons to write it this way:

  1. It's very terse but expressive. People who write a lot of Python can glance at that and understand it.
  2. It's potentially very fast, as the Python interpreter is handling the looping, conditionals, etc. and improvements to the Python interpreter could make the code faster without it having to understand the whole program. Basically you're telling Python "I want this thing done" instead of "here are 100 little steps to do this thing".

I think it returns the total number of matches where actual= expected. Essentially I think it is checking how many times the algorithms model was able to correctly predict

It is a type of List Comprehension that makes use of the zip() function.

Basically, the code is saying:

  • Create a list.
  • Retrieve variables "expected" and "actual" from zip(target, guess). If they are equal, add 1 to the list.
  • Repeat for next values from zip(target, guess).
  • Sum all the 1's.
  • Return this summation.

There are several things going on:

return sum(...)

this means that you are returning a number.

The inner part of the sum is a generator expression which creates and runs an implicit loop.

In this case, 1 for expected, actual in zip(target, guess) if expected == actual creates a sequence of 1 values, with one entry created each time the guard condition is true ( expected == actual ).

So this line is effectively creating code like: sum(1, 1, 1, 1, ...)

Within the generator expression, you have a zip call. The zip expression will take the two (or more!) sequences, and convert them into a single sequence with tuples of two (or more!) values. That is, zip(['a', 'b', 'c'], [1, 2, 3]) will produce as its output a sequence like [('a', 1), ('b', 2), ('c', 3)] .

So if your expected is [1, 2, 3] and your actual is [1, 1, 3] , you will get a zip result like:

expected = [1, 2, 3]
actual = [1, 1, 3]
zip(expected, actual)   # [(1, 1), (2, 1), (3, 3)]

The generator expression contains a for which uses what was once called "tuple unpacking" to assign multiple targets in its target_list from a single aggregate (tuple) value.

So when the zip expression produces (1, 1) the for expected, actual unpacks that into expected=1, actual=1 .

Thus, the zip takes two equal-length sequences and pairs their corresponding elements: a[0] with b[0], a[1] with b[1], etc. The for generator expression assigns those elements into variables called expected and actual . The for...if generator conditional part compares the expected == actual values, and either generates a value or does not generate a value. Thus, the length of the resulting sequence is guaranteed to be less than or equal to the length of the input sequences, but you don't know how long it will be. The expression part of the generator is simply 1 . So you have a variable-length sequence of 1's. It's not 1 or 0. It's 1 or no-entry. Add up all the 1's, and that's the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM