Iterator protocol is implemented whenever you iterate over a sequence of data. For example, when you use a for loop the following is happening on a background:
first iter()method is called on the object to converts it to an iterator object.
next() method is called on the iterator object to get the next element of the sequence.
StopIteration exception is raised when there are no elements left to call.
O que são generators?
Generators são uma forma simples de criarmos iteradores. Ele irá retornar um objeto (iterador) para que nós possamos iterar sobre este objeto (um valor de cada vez).
É muito simples criar uma função Generator, mas existem algumas peculiaridades. Por exemplo, nós usamos a declaração yield ao invés de return. Se a função contém ao menos uma declaração yield então ela se torna uma função Generator.
O yield pode ser lido como um pause, que retorna um objeto do tipo generator.
O objeto Generator só pode ser iterado uma única vez.
Generator expressions
As Generators Expressions facilitam à criação de Generators. Assim como uma função lambda cria uma função anônima, uma Generator Expression cria uma função Generator anônima. A sintaxe é bem parecida com as famosas List Comprehensions com o pequeno detalhe de que os colchetes [ ] são subsituídos pelos parênteses ().
O padrão da maioria dessas expressões é algo dessa forma:
A expressão acima corresponde a função abaixo:
Tuples
listas imutáveis
armazenar registros
Tuples para agrupar dados
Tuple assignment and unpacking (Atribuição múltipla)
O poder das tuplas está no unpacking mechanism. Unpacking é a separação de um tuple (ou qualquer sequência) em várias variáveis. Cada variável recebe um valor do tuple.
Parallel Assignment
Trocar os valores de 2 variáveis
Nesse caso, não precisa de um terceira variável temporária.
Antes:
Tuplas:
Podemos usar (*) to unpack tuple
Função retorna (2 , 4) um par de números que consiste em seu quociente e o resto da divisão.
Então, podemos tentar utilizar a tupla como parâmetro.
No entanto, a função divmod() recebe 2 parâmetros e não apenas 1. Podemos desestrutura a tupla, utilizando simplesmente o caractere (*).
Além disso, já podemos usar o assingment:
Namedtuple
Nesse caso, temos que passar para a função 2 parâmetros:
nome da classe
lista de campos
novos atributos
._fields: exibe o nome dos campos da classe
._make(): pode instanciar uma namedtuple a partir de outra namedtuple.
._asdict(): retorna collections.OrderedDict exibindo também os campos da named tuple.
Uso do * para capturar itens excedentes
args e *kwargs
Antes de mais nada, eles não precisam se chamar args ou kwargs, mas precisam ter o e *, respectivamente! **Os nomes “args” são apenas uma convenção.
Substituímos o valores nos índices 2, 3 e 4 por apenas 2 valores, reduzindo o tamanho da lista.
Operations +* with sequences
Concatenação de sequências
Repetição
Nessas operações novos objetos são criados.
Building lists of lists
Correto
Uma lista que contém 3 listas de 4 itens cada
Errado
Uma lista com 3 referêncis para mesma lista, o que não era nossa intenção.
Operations +=*= with sequences
+= invoca o método especial __iadd__
*= invoca o método especial __imul__
Qual a diferença das operações em listas mutáveis e imutáveis?
Então, várias concatenações em listas imutáveis é ineficiente porque ao invés de apenas adicionar itens na lista, um novo objeto é criado com uma cópia do original.
A+= (corner case)
o interpretador consegue alterar o valor da lista t[2], pois é uma lista
mas não consegue adicionar t[2] na lista t, pois t é uma tupla.
Dá para ver melhor com bytecode:
Alguns aprendizados a partir disso:
não inserir items mutáveis dentro de uma tupla
+= não é uma operação atômica
entender melhor o bytecode pode ser algo útil
list.sort
O método list.sort() ordena a lista in-place - não cria uma cópia do objeto. Tanto que não podemos atribuí-lo para outra variável:
Convenção do Python: Funções ou métodos que alteram objetos in-place sempre retornam None.
sorted function
Algoritmo de ordenação Timsort baseado no Insertion Sort e Merge sort.
A built-in functionsortedcria uma nova lista e a retorna - possui 2 argumentos possíveis (reversed ekey).
Bisect - binary search method in Python
Pode ser usado para buscar um elemento em uma lista.
Ex 1: nesse caso, a função bisect_left retorna o índice da primeira ocorrência do elemento 285.
Ex 2: nesse caso, a função bisect_left retorna o índice da última ocorrência do elemento 285.
lo/hi arguments
bisect.insort
insort(seq, item) - insere um item na sequência de forma a mantê-la ordenada de forma crescente.
# Python program to illustrate
# *args for variable number of arguments
def myFun(*args):
print(type(args))
for arg in args:
print (arg)
myFun('Hello', 'Welcome', 'to', 'GeeksforGeeks')
# <class 'tuple'>
# Hello
# Welcome
# to
# GeeksforGeeks
# Python program to illustrate
# *kargs for variable number of keyword arguments
def myFun(**kwargs):
print(type(kwargs))
for key, value in kwargs.items():
print ("%s == %s" %(key, value))
# Driver code
myFun(first ='Geeks', mid ='for', last='Geeks')
# <class 'dict'>
# first == Geeks
# mid == for
# last == Geeks
a[start:stop:step] # items start through start and skip numbers considering number passed on step
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array