15.12.2022 Views

Python Eficaz

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

contêiner que lê os arquivos contendo os dados de turismo:

class ReadVisits(object):

def __init__(self, data_path):

self.data_path = data_path

def __iter__(self):

with open(self.data_path) as f:

for line in f:

yield int(line)

O novo tipo contêiner funciona corretamente quando passado à função original

sem qualquer modificação.

visits = ReadVisits(path)

percentages = normalize(visits)

print(percentages)

>>>

[11.538461538461538, 26.923076923076923, 61.53846153846154]

Funciona porque o método sum em normalize chama ReadVisits.__iter__ para

alocar um novo objeto iterador. O laço for que normaliza os números também

chama __iter__ para alocar um segundo objeto iterador. Cada um desses

iteradores será progressivamente varrido e exaurido de forma independente,

assegurando que cada iteração única veja todos os valores de dados de entrada. A

única desvantagem dessa técnica é que ela lê os dados de entrada mais de uma

vez.

Agora que entendemos o funcionamento de contêiner como ReadVisits,

podemos escrever funções para assegurar que os parâmetros não sejam simples

iteradores. O protocolo rege que, sempre que um iterador é passado para a

função nativa iter, esta devolve o mesmo iterador. Em contrapartida, quando um

valor do tipo contêiner é passado ao iter, um novo objeto iterador será retornado

a cada vez. Assim, podemos testar a existência desse comportamento para cada

valor de entrada e gerar uma exceção TypeError para rejeitar iteradores.

def normalize_defensive(numbers):

if iter(numbers) is iter(numbers): # Um iterador foi encontrado.

# Fora com ele!

www.full-ebook.com

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!