Em Python

isso aí é uma linha

Quem sou eu

Tyrone Damasceno

Apaixonado por Python e membro do Grupy-RN

Desenvolvedor back-end na Evolux

Bacharel em TI pela UFRN

Burger lover

@tyronedamasceno

O que vamos ver hoje?

import base64, sys; base64.decode(open(sys.argv[1], "rb"), open(sys.argv[2], "wb"))
import sys,os,re,fileinput;a=[i[2] for i in os.walk('.') if i[2]] [0];[
                sys.stdout.write(re.sub('at','op',j)
                for j in fileinput.input(a,inplace=1)]

print (
        '\n'.join("%i Byte = %i Bit = largest number: %i" % (j, j*8, 256**j-1)
        for j in (1 << i for i in xrange(8)))
      )

f = lambda x: [
    [y for j, y in enumerate(set(x)) if (i >> j) & 1] for i in range(2**len(set(x)))]

Sério, o que veremos hoje?

  • Iteradores
  • List Comprehensions
  • Geradores
  • Expressões Geradoras

Como, quando e por quê usar!

Iteradores

Tudo aquilo em que se pode iterar, ou seja, percorrer com um laço for.

>>> numeros = [1, 2, 3, 4, 5, 6, 7]
>>> for n in numeros:
...     if n % 2 == 0:
...             print(n)
...
2
4
6
>>>

List Comprehensions

  • É uma forma de construir novos iteráveis.
  • Ou de transformar iteráveis
  • Não é pra economizar linhas

List Comprehensions

>>> numeros = [1, 2, 3, 4, 5, 6, 7]
>>> pares = []
>>> for n in numeros:
...     if n % 2 == 0:
...         pares.append(n)
...
>>> print(pares)
[2, 4, 6]

Criando uma lista de pares

List Comprehensions

>>> numeros = [1, 2, 3, 4, 5, 6, 7]
>>> pares = [n for n in numeros if n % 2 == 0]
>>> print(pares)
[2, 4, 6]

Criando uma lista de pares

[item for item in iteravel if item % 2 == 0]

List Comprehensions

Criando listas de listas

>>> lista_de_listas = [
...     [x + y for x in range(3)]
...     for y in range(3)
... ]
>>> lista_de_listas
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> 
>>> type(lista_de_listas)
<class 'list'>
>>> type(lista_de_listas[0])
<class 'list'>

List Comprehensions

Modificando uma lista

>>> galera_massa = ['Tyrone', 'GeRaLdO', 'ALLYTHY', 'Sedir']
>>> galera_massa = [nome.lower() for nome in galera_massa]
>>> galera_massa
['tyrone', 'geraldo', 'allythy', 'sedir']

List Comprehensions

"Readability counts."

numeros = [1, 2, 3, 4, 5, 6, 7]
lista_bolada = [(n**2/6) for n in numeros if is_prime(n) else 44]

"Readability counts."

List Comprehensions

"Readability counts."

numeros = [1, 2, 3, 4, 5, 6, 7]
lista_bolada = [
                (n**2/6)
                for n in numeros
                if is_prime(n)
                else 44
            ]

"Readability counts."

Set e dict comprehensions

>>> my_set = {
...    x**2
...    for x in range(-2, 3)
...}
>>> my_set
{0, 1, 4}
>>> type(my_set)
<class 'set'>
>>> my_dict = {
...     x: x**2
...     for x in range(-2, 3)
... }
>>> my_dict
{-2: 4, -1: 1, 0: 0, 1: 1, 2: 4}
>>> type(my_dict)
<class 'dict'>

Set comprehension

Dict comprehension

Geradores

  • Criar um iterador de forma lazy
  • Geração dos valores sob demanda
  • Pausar a criação do iterável
  • Só podem ser usados uma vez

Expressões geradoras

  • Por que não "generator comprehension"? 
  • Servem para criar geradores
  • Use quando precisa iterar sobre uma lista uma única vez
  • Basicamente troca os colchetes por parênteses
>>> a = [x+7 for x in range(4)]
>>> a
[7, 8, 9, 10]
>>> type(a)
<class 'list'>
>>> a = (x+7 for x in range(4))
>>> a
<generator object <genexpr> at 0x1b>
>>> type(a)
<class 'generator'>

Geradores

  • Não sabem quantos valores possuem, e isso permite criar geradores infinitos
>>> gerador_gigante = (x for x in range(1000000000000))
>>> len(gerador_gigante)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()

Geradores

  • Mas você pode criar uma lista, ou um set com um gerador, por exemplo
>>> fibonelson = [1, 1, 2, 3, 5, 8, 11, 19]
>>> fib_quadrado = (fib**2 for fib in fibonelson)
>>> type(fib_quadrado)
<class 'generator'>
>>> lista_fibs_quadrados = list(fib_quadrado)
>>> lista_fibs_quadrados
[1, 1, 4, 9, 25, 64, 121, 361]

Geradores

  • Sempre lembrando que o gerador vai iterar uma unica vez
>>> fibonelson = [1, 1, 2, 3, 5, 8, 11, 19]
>>> fib_quadrado = (fib**2 for fib in fibonelson)
>>> lista_fibs_quadrados = list(fib_quadrado)
>>> lista_fibs_quadrados_2 = list(fib_quadrado)
>>> lista_fibs_quadrados
[1, 1, 4, 9, 25, 64, 121, 361]
>>> lista_fibs_quadrados_2
[]
>>> fib_quadrado
<generator object <genexpr> at 0x102bfcc78>
>>> next(fib_quadrado)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Geradores

  • O método next é o responsável por iterar, e é ele que nos permite chamar um gerador de lazy
>>> gerador_de_pares = (x*2 for x in range(10))
>>> next(gerador_de_pares)
0
>>> next(gerador_de_pares)
2
>>> next(gerador_de_pares)
4
>>> # Algumas chamadas...
>>> next(gerador_de_pares)
18
>>> next(gerador_de_pares)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Geradores

  • O método next é o responsável por iterar, e é ele que nos permite chamar um gerador de lazy
>>> gerador_de_pares = (x*2 for x in range(10))
>>> next(gerador_de_pares)
0
>>> next(gerador_de_pares)
2
>>> next(gerador_de_pares)
4
>>> # Algumas chamadas...
>>> next(gerador_de_pares)
18
>>> next(gerador_de_pares)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Geradores

  • Podemos chamar funções diretamente sobre geradores ou expressões geradoras
>>> numberos = [1, 2, 3, 4, 5]
>>> numeros = [1, 2, 3, 4, 5]
>>> quadrados = (x**2 for x in numbs)
>>> sum(quadrados)
55
>>> sum(quadrados)
0
>>> sum((x**2 for x in numbs))
55
>>> sum(x**2 for x in numbs)
55

Vou sair metendo comprehension em tudo?

  • Não
  • Não
  • Talvez

Quando não usar

  • Quando não é necessário
>>> [print(x) for x in range(5)]
0
1
2
3
4
[None, None, None, None, None]

Quando não usar

  • Quando afeta a legibilidade
print (
        '\n'.join("%i Byte = %i Bit = largest number: %i" % (j, j*8, 256**j-1)
        for j in (1 << i for i in xrange(8)))
      )

Quando não usar

  • Quando gastar mais linhas que usando o for
>>> frutas = ['Abacaxi', 'Uva', 'Laranja', 'Mangaba']
>>> nota_do_suco = [7, 8.3, 9, 10]
>>> fruta_e_nota = {}

>>> for fruta, nota in zip(frutas, nota_do_suco):
...     fruta_e_nota[fruta] = nota
...

>>> fruta_e_nota_comp = {
...     fruta: nota
...     for fruta, nota in zip(frutas, nota_do_suco)
... }

>>> fruta_e_nota == fruta_e_nota_comp
True

Quando não usar

  • Lembrem que estamos falando de Python, sempre dá pra fazer em uma linha!
>>> fruta_e_nota = dict(zip(frutas, nota_do_suco))
>>> fruta_e_nota
{'Abacaxi': 7, 'Uva': 8.3, 'Laranja': 9, 'Mangaba': 10}

Obrigado!

Estou disponível em 

@tyronedamasceno no telegram, instagram, github...

Em Python isso aí é uma linha

By Tyrone Damasceno

Em Python isso aí é uma linha

  • 91