Generator Expressions

Asked

Viewed 113 times

2

Good, I’ve been trying to optimize my code and I found Enerator Expressions, only I don’t understand any of it.

For example:

for mCp in mWithoutNone:
    for ctt in moradasCTT:
        if mCp[3] == ctt[3]:
            mWithCp4.append( ctt )
        else:
            pass

and wanted to be like:

for mCp in mWithoutNone: # necessito mesmo deste for aqui por causa de uns if que tenho mais a frente
    mCp[3] == ctt[3] if mWithCp4.append( ctt ) else '' for ctt in moradasCTT

Complete code: https://pastebin.com/WtD6XbVT

2 answers

1


(TL;DR)
Generating expressions, or genexp is a very broad subject in python, but maybe what you need is list comprehensions or listcomps, I’ll try to give an example here using the approach, with for, with liscomps and a small sample of genexps.

Let’s say we have a list of numbers:

[1,2,5,10,20,4,5,7.18,55,34,14,44,89,70,64]

and we need to extract from it only those divisible by 2. The first option would be:

Approach with for:

lst1 = [1,2,5,10,20,4,5,7.18,55,34,14,44,89,70,64]
lst2 = []

for number in lst1:
  if number%2==0:
    lst2.append(number)

Output:

print (lst2)
[2, 10, 20, 4, 34, 14, 44, 70, 64]

Now let’s see how you’d look wearing listcomps.

Using listcomps:

## Usando listcomps ##
listcomps1 = [number for number in lst1 if number%2==0]

Output:

 print('listcomps1 (listcomps) :',listcomps1,'\n')
 listcomps1 (listcomps) : [2, 10, 20, 4, 34, 14, 44, 70, 64] 

Using genexp:

## Usando Expressões geradoras ##
gen1 = (number for number in lst1 if number%2==0)

Note that to generate generating explressão, the syntax is identical to the generation of listcomps, the only difference is the use of parentheses instead of brackets, but let’s see the result:

output:

print('gen1 (genexp) : ', gen1,'\n')
gen1 (genexp) :  <generator object <genexpr> at 0x7fb9f4d705c8> 

Note that the result was not a list but a objeto, this object can be 'manipulated' in several ways, we could do, for example:

print (list(gen1))

And we would get as a result exactly what we get with listcomp, i.e., [2, 10, 20, 4, 34, 14, 44, 70, 64], but 'kill' the generating expression and the result of the next example would generate an error.

Featuring the fifth element of genexp:

Taking into account that in the code we do not include the command of the previous topic print (list(gen1)), we could display any element of genexp without creating an entire list.

## Apresentando o 5 elemento da gen1?
print ('Quinto elemento: ', list(gen1)[5], '\n')

Output:

Quinto elemento:  14 

Showing that genexp "died" after run:

## Mostrando que a gen1 foi executada e "morreu": ##
print ('O que aconteceu com gen1: ', list(gen1))

Output:

O que aconteceu com gen1:  []

So what’s the advantage of genexps?
The main advantage of genexps is that they do not create, a priori, an entire list in memory. of course in examples such as those presented here, there are no significant advantages, but suppose in the example above the source is not an internal list but rather some external artifact (a database, for example) with thousands or millions of elements, and the need was to access specific elements in the resulting (such as the fifth element, from the example), in this case, Voce would result only in genexp and not the entire list. Of course the explanation was minimalist, for a broader view, see the PEP 289.

Run the code in repl.it.

1

Generator Expressions has a simple syntax:

(expressão for variavel in interavel if condição)

if you want all values, you can omit the condition, hence:

(expressão, for variavel in iteravel)

both are equivalent to:

def generator():
    for variavel in iteravel:
        if condição:
            yield expressão #poderia ser: variavel + 1.5 por exemplo

I will make an example in portugol and python

para cada numero entre 0 e 100 selecione os numeros divisiveis por 2

could be translated into python as:

>>> [numero for numero in range(0, 101) if numero % 2 == 0]
retorna:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]

This is actually a list and not a General because of the brackets. however if replacing the brackets by parentheses this becomes a Generator Object that only contains the expression but does not store all values in a list, Oce can interact normally on it but cannot access indices as it does not store data.

#criando gerador
>>> gerador = (numero for numero in range(0, 101) if numero % 2 == 0)
>>> gerador
<generator object <genexpr> at 0x02DDF240>
#interando sobre ele
>>> for x in gerador:
    print(x)

0
2
4
6
8
10
12
14
...
#tentando acessar um indice falha pois geradores não são listas
>>> gerador[10]
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    gerador[10]
TypeError: 'generator' object is not subscriptable
>>> 

Browser other questions tagged

You are not signed in. Login or sign up in order to post.