diff --git a/roteiros/00_introducao.md b/roteiros/00_introducao.md index b3d85ef..8ac9f39 100644 --- a/roteiros/00_introducao.md +++ b/roteiros/00_introducao.md @@ -4,18 +4,18 @@ Sinta-se um vencedor, se você chegou até aqui, isso significa que quer aprender mais sobre o mundo da programação. -Aprender novos paradígmas podem te trazer muitas coisas positivas, assim como aprender linguagens diferentes, pois paradígmas e linguagens transpõem maneiras, estruturas e métodos de implementação completamente diferentes. Com isso você pode ter mais ferramentas para usar no dia a dia. Você pode aumentar sua capacidade de expressar ideias de diferentes maneiras. Eu penso que o maior limitador de um programador é a linguagem de programação em que ele tem domínio. Quando você aprende linguagens imperativas, como C, Python, Java e etc..., você se vê limitado ao escopo de criar e manipular variáveis. Não que isso seja uma coisa ruim, porém existem outras maneiras de resolver problemas e quando você tem conhecimento disso consegue avaliar melhor quando implementar cada tipo de coisa. +Aprender novos paradigmas podem te trazer muitas coisas positivas, assim como aprender linguagens diferentes, pois paradigmas e linguagens transpõem maneiras, estruturas e métodos de implementação completamente diferentes. Com isso você pode ter mais ferramentas para usar no dia a dia. Você pode aumentar sua capacidade de expressar ideias de diferentes maneiras. Eu penso que o maior limitador de um programador é a linguagem de programação em que ele tem domínio. Quando você aprende linguagens imperativas, como C, Python, Java e etc..., você se vê limitado ao escopo de criar e manipular variáveis. Não que isso seja uma coisa ruim, porém existem outras maneiras de resolver problemas e quando você tem conhecimento disso consegue avaliar melhor quando implementar cada tipo de coisa. -Você pode me dizer que aprender diferentes tipos de estruturas e maneiras de computar é uma coisa negativa pois tudo é variável nesse contexto. Mas eu penso exatamente o contrário, quanto mais você aprender da sua língua nativa, no caso estamos falando em português, maior o campo de domínio que você tem sobre como se comunicar e expressar ideias. Assim como aprender outras línguas te darão mais fundamentos para expressar ideias em outros idiomas, que não são melhores que os seu, mas diferentes e compõem diferentes estruturas, e isso pode ser libertador. Não quero me prolongar nesse assunto, mas dizer que isso pode acrescentar muito na suas habilidades cognitivas, até mesmo para usar ferramentas que você já usa no seu dia a dia. +Você pode me dizer que aprender diferentes tipos de estruturas e maneiras de computar é uma coisa negativa pois tudo é variável nesse contexto. Mas eu penso exatamente o contrário, quanto mais você aprender da sua língua nativa, no caso estamos falando em português, maior o campo de domínio que você tem sobre como se comunicar e expressar ideias. Assim como aprender outras línguas te darão mais fundamentos para expressar ideias em outros idiomas, que não são melhores que os seu, mas diferentes e compõem diferentes estruturas, e isso pode ser libertador. Não quero me prolongar nesse assunto, mas dizer que isso pode acrescentar muito nas suas habilidades cognitivas, até mesmo para usar ferramentas que você já usa no seu dia a dia. -Vamos começar fazendo uma tentativa de entender os paradígmas de programação, sem muito falatório e complicações. Um exemplo muito legal é do David Mertz em "Functional Programming in Python": +Vamos começar fazendo uma tentativa de entender os paradigmas de programação, sem muito falatório e complicações. Um exemplo muito legal é do David Mertz em "Functional Programming in Python": - Usa-se programação funcional quando se programa em Lisp, Haskell, Scala, Erlang, F# etc.. - Do mesmo modo que se usa programação imperativa quando se programada C/C++, Pascal, Java, Python etc... -- Também quando se programa Prolog estamos programando usando o paradígma lógico. +- Também quando se programa Prolog estamos programando usando o paradigma lógico. Apesar de não ser uma definição muito elegante, talvez seja a melhor a ser dada em muitas ocasiões. Vamos tentar ser um pouco mais objetivos em relação ao estilo de computação, embora essa discussão não tenha fim: @@ -27,7 +27,7 @@ Apesar de não ser uma definição muito elegante, talvez seja a melhor a ser da ## 0.1 Mas de onde vem a programação funcional? -O florescer da programação funcional nasce no Lisp (acrônomo para List Processing) para tentar resolver alguns problemas de inteligência artificial que eram provenientes da linguística, que tinha foco em processamento de linguagem natural que por sua vez eram focados em processamento de listas em geral. Isso justifica uma grande parte do conteúdo que vamos ver aqui e seus tipos de dados variam somente entre listas e átomos. E assim foi mantido o foco de processamento de listas em todas as linguagens funcionais e suas funções e abstrações para resolver problemas relativos a listas e estruturas iteráveis. Uma curiosidade é que para quem não sabe porque em lisp existem tantos parênteses é que ele é baseado em s-expression, uma coisa que temos um "equivalente" evoluído em python, que parte dos teoremas de gramáticas livres de contexto: +O florescer da programação funcional nasce no Lisp (acrônimo para List Processing) para tentar resolver alguns problemas de inteligência artificial que eram provenientes da linguística, que tinha foco em processamento de linguagem natural que por sua vez eram focados em processamento de listas em geral. Isso justifica uma grande parte do conteúdo que vamos ver aqui e seus tipos de dados variam somente entre listas e átomos. E assim foi mantido o foco de processamento de listas em todas as linguagens funcionais e suas funções e abstrações para resolver problemas relativos a listas e estruturas iteráveis. Uma curiosidade é que para quem não sabe porque em lisp existem tantos parênteses é que ele é baseado em s-expression, uma coisa que temos um "equivalente" evoluído em python, que parte dos teoremas de gramáticas livres de contexto: ```clojure (+ 4 5) @@ -73,16 +73,16 @@ Vamos tentar mapear o que as linguagens funcionais fazem de diferente das lingua - Como dito anteriormente, pensar em como as sequências podem nos ajudar a resolver problemas. - O que deve ser computado, não como computar: - - Não ser tão expressivo e aceitar que as intruções não tem necessidade de estar explicitas todas as vezes, isso ajuda em legibilidade. + - Não ser tão expressivo e aceitar que as intruções não tem necessidade de estar explícitas todas as vezes, isso ajuda em legibilidade. - Lazy evaluation: - Criar sequências infinitas sem estourar nossa memória. ## 0.3 Python é uma linguagem funcional? -#### Não. Mas é uma linguagem que implementa muitos paradígmas e porque não usar todos de uma vez? +#### Não. Mas é uma linguagem que implementa muitos paradigmas e porque não usar todos de uma vez? -O objetivo desse 'conjunto de tópicos' é escrever código que gere menos efeito colateral e código com menos estados. Só que isso tudo feito na medida do possível, pois Python não é uma linguagem funcional. Porém, podemos contar o máximo possível com as features presentes do paradígma em python. +O objetivo desse 'conjunto de tópicos' é escrever código que gere menos efeito colateral e código com menos estados. Só que isso tudo feito na medida do possível, pois Python não é uma linguagem funcional. Porém, podemos contar o máximo possível com as features presentes do paradigma em python. Exemplos de funcional (básicos) em python: @@ -124,7 +124,7 @@ Jaber é nosso aluno de mentira, mas vamos pensar que ele é um aluno que senta Não gosto muito de citar referências pois procurei não copiar texto dos livros, mas muita coisa contida neles serve de base para o entendimento de certos tópicos. Outro motivo é o nível de complexidade dos exemplos ou explicações que tentei reduzir ao máximo enquanto escrevia esses roteiros. Para um exemplo, você pode olhar o livro do Steven Lott, cheio de fórmulas e abstrações matemáticas que em certo ponto acabam comprometendo o entendimento de quem não tem uma sólida base em computação teórica ou matemática. -Como um todo, as referências serviram como guia, foi o que lí quando dúvidas para explicações surgiram. Não tiro nenhum crédito delas e as exponho para que todos saibam que existem muitos livros bons e que boa parte do que é passado aqui, foi aprendido neles. +Como um todo, as referências serviram como guia, foi o que li quando dúvidas para explicações surgiram. Não tiro nenhum crédito delas e as exponho para que todos saibam que existem muitos livros bons e que boa parte do que é passado aqui, foi aprendido neles. ## 0.7 Mais sobre o histórico das linguagens funcionais diff --git a/roteiros/01_funcoes.md b/roteiros/01_funcoes.md index 2d7541d..628a759 100644 --- a/roteiros/01_funcoes.md +++ b/roteiros/01_funcoes.md @@ -164,7 +164,7 @@ Isso quer dizer que podemos gerar classes que se comportam como funções? SIIIIIM. Chupa Haskell -Essa é uma parte interessante da estrutura de criação do Python a qual veremos mais em outro momento sobre introspecção de funções, mas vale a pena dizer que classes, funções nomeadas, funções anônimas e funções geradoras usam uma base comum para funcionarem, essa é uma das coisas mais bonitas em python e que em certo ponto fere a ortogonalidade da linguagem, pois coisas iguais tem funcionamentos diferentes, mas facilita o aprendizado da linguagem, mas não é nosso foco agora. +Essa é uma parte interessante da estrutura de criação do Python a qual veremos mais em outro momento sobre introspecção de funções, mas vale a pena dizer que classes, funções nomeadas, funções anônimas e funções geradoras usam uma base comum para funcionarem, essa é uma das coisas mais bonitas em python e que em certo ponto fere a ortogonalidade da linguagem, pois coisas iguais têm funcionamentos diferentes, mas facilita o aprendizado da linguagem, mas não é nosso foco agora. ## 1.5 Funções geradoras diff --git a/roteiros/02_iteraveis_iteradores.md b/roteiros/02_iteraveis_iteradores.md index d2b0ba4..0c17ee3 100644 --- a/roteiros/02_iteraveis_iteradores.md +++ b/roteiros/02_iteraveis_iteradores.md @@ -111,7 +111,7 @@ Seguem dois links maravilhosos explicando sobre iteração em python: - [Iteração em Python: do básico ao genial](https://www.youtube.com/watch?v=ULj7ejvuzI8) -O primeiro é a PEP sobre as estruturas dos iteráveis e o segundo um video do Guru Luciano Ramalho explicando tudo sobre iteradores. +O primeiro é a PEP sobre as estruturas dos iteráveis e o segundo um vídeo do Guru Luciano Ramalho explicando tudo sobre iteradores. Ah... Ia quase me esquecendo, se você não entendeu muita coisa sobre os dunders, você pode ler o [Python data model](https://docs.python.org/3/reference/datamodel.html#special-method-names). Obs: não me responsabilizo pelo programador melhor que você sairá desta página. diff --git a/roteiros/03_consumindo_iteraveis.md b/roteiros/03_consumindo_iteraveis.md index 7dc73f9..f8c5147 100644 --- a/roteiros/03_consumindo_iteraveis.md +++ b/roteiros/03_consumindo_iteraveis.md @@ -19,7 +19,7 @@ for x in [1, 2, 3, 4, 5]: # 5 ``` -Porém, esse "for", aos meus olhos, só vale pra printar coisas, não? Pense comigo. Toda vez que realmente iteramos em alguma sequência, nós queremos os valores, queremos modificá-los, querendo incrementar, criar novos objetos e por ai vai... +Porém, esse "for", aos meus olhos, só vale pra printar coisas, não? Pense comigo. Toda vez que realmente iteramos em alguma sequência, nós queremos os valores, queremos modificá-los, querendo incrementar, criar novos objetos e por aí vai... Existem muitas maneiras diferentes e até mais eficientes, não briguem comigo, de iterar sobre sequências. Uma delas é uma list comprehensions. @@ -115,6 +115,6 @@ Acaba-se de reproduzir o estado de amor Pythonico agora. Você foi funcional! T Tá, agora você já sabe o poder que tem nas mãos. Nunca mais declare uma lista vazia para receber appends, combinado? -Agora que você é um entendedor da iterações, vamos complicar um pouco e falar sobre functors, monads e catamorphismo. Tá, mas sem palavras difíceis, os seus coleguinhas não gostam de nomenclaturas haskelianas. Mas você vai poder esnobar seus conhecimentos teóricos sobre Teoria das Categorias. Até o próximo tópico. +Agora que você é um entendedor das iterações, vamos complicar um pouco e falar sobre functors, monads e catamorphismo. Tá, mas sem palavras difíceis, os seus coleguinhas não gostam de nomenclaturas haskelianas. Mas você vai poder esnobar seus conhecimentos teóricos sobre Teoria das Categorias. Até o próximo tópico. [Retorne <<< 2. Iteráveis e iteradores](./02_iteraveis_iteradores.md) - [Continue lendo >>> 4. Funções de redução/mapeamento](./04_funcoes_reducao_mapeamento.md) diff --git a/roteiros/04_funcoes_reducao_mapeamento.md b/roteiros/04_funcoes_reducao_mapeamento.md index ffb6c99..678c5f2 100644 --- a/roteiros/04_funcoes_reducao_mapeamento.md +++ b/roteiros/04_funcoes_reducao_mapeamento.md @@ -260,7 +260,7 @@ print(list(reversed(lista))) # [5, 4, 3, 2, 1] # construtor de um conjunto print(set(reversed(lista))) # {5, 4, 3, 2, 1} -# construtor de uma lista +# construtor de uma tupla print(tuple(reversed(lista))) # (5, 4, 3, 2, 1) ``` diff --git a/roteiros/05_hofs.md b/roteiros/05_hofs.md index 8a09cae..6dcf6a7 100644 --- a/roteiros/05_hofs.md +++ b/roteiros/05_hofs.md @@ -214,7 +214,7 @@ Ou seja, é passado um objeto com um método no lugar de uma função. O método ## 5.5 sorted() -Para os viciados em listas, como eu, o método sort da lista funciona bem, apesar de ordenar a lista e não trazer uma nova lista, o que as vezes é uma dor de cabeça. +Para os viciados em listas, como eu, o método sort da lista funciona bem, apesar de ordenar a lista e não trazer uma nova lista, o que às vezes é uma dor de cabeça. ```Python lista = [1, 2, 3, 3, 2, 1] diff --git a/roteiros/06_funcoes_geradoras_e_hofs_p2.md b/roteiros/06_funcoes_geradoras_e_hofs_p2.md index f6281b3..30cc263 100644 --- a/roteiros/06_funcoes_geradoras_e_hofs_p2.md +++ b/roteiros/06_funcoes_geradoras_e_hofs_p2.md @@ -164,7 +164,7 @@ Agora que você já conhece mais um tipo de função, vamos voltar as nossas HOF Como já sabemos e já foi dito exaustivamente, funções são objetos de primeira classe em Python. Já sabemos. Ok. -Então como já entendemos tudo isso, vamos só usar alguns exemplos de funções que recebem funções. OBS: Vamos criar algumas funções meio especialistas agora, isso não é muito bom. Mas serve como base de aprendizado. No proxímo tópico vamos explorar mais funções simples e que são de grande utilidade em muitos contextos, porém... +Então como já entendemos tudo isso, vamos só usar alguns exemplos de funções que recebem funções. OBS: Vamos criar algumas funções meio especialistas agora, isso não é muito bom. Mas serve como base de aprendizado. No próximo tópico vamos explorar mais funções simples e que são de grande utilidade em muitos contextos, porém... Vamos trabalhar em outra frente então: @@ -265,6 +265,6 @@ Counter('abacaxi verde limão verde como coco verde'.split()) # Counter({'abacax Tá, vai... A gente tentou e você aprendeu. SUAHSUAHUSHA. -Com isso, no próximo tópico, vamos construir nossa propria lib de HOFs simples e que servem para tudo. Um abraço. +Com isso, no próximo tópico, vamos construir nossa própria lib de HOFs simples e que servem para tudo. Um abraço. [Retornar <<< 5. Funções de ordem superior](./05_hofs.md) - [Continue lendo >>> 7. Nossa primeira biblioteca de funções](./07_construindo_nossa_lib.md) diff --git a/roteiros/07_construindo_nossa_lib.md b/roteiros/07_construindo_nossa_lib.md index 1110546..2817e5e 100644 --- a/roteiros/07_construindo_nossa_lib.md +++ b/roteiros/07_construindo_nossa_lib.md @@ -17,10 +17,10 @@ def tail(seq, n=1, key=None): Pode parecer uma função extremamente simples, mas ela é bem legal. Dá pra conseguir muitos resultados legais com ela: ```Python -'Por padrão vai retornar só o ultimo' +'Por padrão vai retornar só o último' tail([1,2,3,4]) # [4] -'Aqui usamos n, que nesse caso retorna os ultimos 3 elementos' +'Aqui usamos n, que nesse caso retorna os últimos 3 elementos' tail([1,2,3,4], 3) # [2, 3, 4] 'O resultado reverso' @@ -134,7 +134,7 @@ Se você analisar de perto, drop() tem um comportamento muito parecido com a fun drop(n, seq) ``` -`n` é o valor que queremos ignorar de `seq`. Em uma chamada `n=5` de uma sequência de 6 valores, só o último valor será retonado. O que faz o comportamento da função ser exatamente inverso ao take() que nos retornaria os primeiros cinco valores. Tá bom, falamos muito, vamos tentar implementar: +`n` é o valor que queremos ignorar de `seq`. Em uma chamada `n=5` de uma sequência de 6 valores, só o último valor será retornado. O que faz o comportamento da função ser exatamente inverso ao take() que nos retornaria os primeiros cinco valores. Tá bom, falamos muito, vamos tentar implementar: ```Python @@ -166,7 +166,7 @@ Imagina pegar o resultado de uma função e atribuir a entrada de outra função # cat - mostra o conteúdo do arquivo na tela, porém mostrar na tela é uma saída para STDOUT (saída padrão) # oi.txt - é um arquivo de texto que contém as linhas (oi Jaber \n oi Eduardo \n Oi dinossauros) # | - é um pipe -# grep - é um comando usado para procurar uma determinada string (grep oi) vai exibir todas as linhas do arquivo que comtém a string oi +# grep - é um comando usado para procurar uma determinada string (grep oi) vai exibir todas as linhas do arquivo que contém a string oi cat oi.txt | grep Jaber diff --git a/roteiros/10_decoradores.md b/roteiros/10_decoradores.md index 6d59c13..1df335e 100644 --- a/roteiros/10_decoradores.md +++ b/roteiros/10_decoradores.md @@ -57,7 +57,7 @@ Não é preciso ser um gênio como o Jaber para saber como usar essa função: ```Python >>> soma(1, 1) # 2 >>> soma(2.0, 2.0) # 4.0 ->>> soma(3j + 3j) # 6j +>>> soma(3j, 3j) # 6j ``` Ela funciona efetivamente com todos os tipos de números em Python. Embora seja possível imaginar que nossa função usa o operador `+`. Ele faz com que nossos objetos numéricos invoquem seu método mágico interno `__add__` ou `__radd__`. O único problema é que outros objetos em Python também implementam esse método. Strings e listas podem usar o `__add__`, mas somente entre sí. Vale lembrar aqui que Python é uma linguagem fortemente tipada. Eu não vou conseguir somar uma string com um inteiro ou com uma lista por exemplo. @@ -168,7 +168,7 @@ def mul(x, y): # 2 >>> soma(2.0, 2.0) # 4.0 ->>> soma(3j + 3j) +>>> soma(3j, 3j) # 6j >>> mul(1, 1) # 2 @@ -258,7 +258,7 @@ def timeit(func): """ Decorador para medir o tempo. - Roubada de: Python Cookbook 3ª edição (Beazley e Jone - O'Reilly) + Roubada de: Python Cookbook 3ª edição (Beazley e Jones - O'Reilly) """ def inner(*args): ts = time() # pega a 'hora' atual @@ -271,14 +271,14 @@ def timeit(func): return inner ``` -Esse é um decorador bem simples de se entender. Ele vai decorar uma função e nós saberemos o tempo que ela levou para ser executada em segundos. Você pode pensar que esse decorador é mais do mesmo, porém, ele nos mostra quão genéricos devem ser os decoradores. A ídeia é de que possam ser usados em qualquer lugar. Nesse caso `eh_par` acaba sendo um contra-exemplo de um bom decorador. Mas, vale lembrar que o objetivo dele é totalmente didático. Sei que você já deve ter entendido tudo sobre decoradores. Porém, eles também podem receber argumentos, o que os tornariam mais genéricose potentes. Então, vamos lá... +Esse é um decorador bem simples de se entender. Ele vai decorar uma função e nós saberemos o tempo que ela levou para ser executada em segundos. Você pode pensar que esse decorador é mais do mesmo, porém, ele nos mostra quão genéricos devem ser os decoradores. A ideia é de que possam ser usados em qualquer lugar. Nesse caso `eh_par` acaba sendo um contra-exemplo de um bom decorador. Mas, vale lembrar que o objetivo dele é totalmente didático. Sei que você já deve ter entendido tudo sobre decoradores. Porém, eles também podem receber argumentos, o que os tornariam mais genéricos e potentes. Então, vamos lá... ## 10.3 Decoradores com parâmetros -Uma das coisas mais legais de quando se está aprendendo Python, é que em um certo momento você acaba entendendo a ideia de que não podemos fazer código com alto acoplamento. Por exemplo, nos ultimos tópicos você simplesmente definiu uma `def` dentro de outra `def`. Porém, as coisas podem ser mais simpáticas quando você simplesmente se dá o prazer de experimentar. +Uma das coisas mais legais de quando se está aprendendo Python, é que em um certo momento você acaba entendendo a ideia de que não podemos fazer código com alto acoplamento. Por exemplo, nos últimos tópicos você simplesmente definiu uma `def` dentro de outra `def`. Porém, as coisas podem ser mais simpáticas quando você simplesmente se dá o prazer de experimentar. -Por exemplo, e se fizessemos uma closure de uma closure? +Por exemplo, e se fizéssemos uma closure de uma closure? ```Python def param(args): @@ -319,7 +319,7 @@ def soma(*args): return sum(args) ``` -Embora quem faça a frente da nossa função seja `verbose`, o decorador real, a função que recebe a nossa função é a `funcao_externa`, como em todos os exemplos. A função `verbose` nesse caso, vai simplemente adicionar uma camada a mais no escopo local da função `funcao_externa` e por consequência também no escopo da `funcao_interna`. Ou seja, você pode parametrizar a execução do decorador sem que a parametrização seja feita com os argumentos passados a função decorada. +Embora quem faça a frente da nossa função seja `verbose`, o decorador real, a função que recebe a nossa função é a `funcao_externa`, como em todos os exemplos. A função `verbose` nesse caso, vai simplesmente adicionar uma camada a mais no escopo local da função `funcao_externa` e por consequência também no escopo da `funcao_interna`. Ou seja, você pode parametrizar a execução do decorador sem que a parametrização seja feita com os argumentos passados a função decorada. ## 10.4 Identidade das funções decoradas @@ -387,9 +387,9 @@ def com_decorador(x, y): # ``` -Com isso, uma cópia dos métodos `__module__`, `__name__`, `__qualname__`, `__annotations__` e `__doc__` será feita na função "embrulhada" (wraped) e as propriedades da função decorada continuarão a ser mantidas após o embrulho. Ou seja, poderemos tanto facilitar a vida quando for necessário depurar nosso código e também o autocomplete do seu editor, a função `help()` e todas as coisas que precisam determinar o comportamento da sua função continuariam a funcionar como se a função não estivesse decorada. Porém, ela agora será uma função embrulhada. Ou seja, quando a função for chamada ela vai ser invocada pelo embrulho e você perderá a visualização da representação sem o decorador de `wraps` (`.inner>`). Para isso, existe na função embrulhada um método chamado `__wrapped__` que corresponde exatamente à função `.inner>`. Com isso, você agora pode usar a função sem se preocupar com o comportamento do decorador e caso precise desse tipo de interação, você pode invocar diretamente `com_decorador.__wrapped__`. Então você não precisa mais se preocupar com diferentes tipos de interação e manter a sanidade mental. +Com isso, uma cópia dos métodos `__module__`, `__name__`, `__qualname__`, `__annotations__` e `__doc__` será feita na função "embrulhada" (wrapped) e as propriedades da função decorada continuarão a ser mantidas após o embrulho. Ou seja, poderemos tanto facilitar a vida quando for necessário depurar nosso código e também o autocomplete do seu editor, a função `help()` e todas as coisas que precisam determinar o comportamento da sua função continuariam a funcionar como se a função não estivesse decorada. Porém, ela agora será uma função embrulhada. Ou seja, quando a função for chamada ela vai ser invocada pelo embrulho e você perderá a visualização da representação sem o decorador de `wraps` (`.inner>`). Para isso, existe na função embrulhada um método chamado `__wrapped__` que corresponde exatamente à função `.inner>`. Com isso, você agora pode usar a função sem se preocupar com o comportamento do decorador e caso precise desse tipo de interação, você pode invocar diretamente `com_decorador.__wrapped__`. Então você não precisa mais se preocupar com diferentes tipos de interação e manter a sanidade mental. -Mas, uma coisa um pouco diferente aconteceu nesse exemplo com `@wraps`, existe um novo decorador inserido dentro da função interna do decorador e é isso que vamos ver no proximo tópico. +Mas, uma coisa um pouco diferente aconteceu nesse exemplo com `@wraps`, existe um novo decorador inserido dentro da função interna do decorador e é isso que vamos ver no próximo tópico. ## 10.5 Decorando decoradores @@ -399,11 +399,11 @@ Como você deve ter percebido, não existem mais limites entre decorar funções ```Python @decorador1 @decorador2 -def funcao_que_redebe_dois_decoradores(): +def funcao_que_recebe_dois_decoradores(): pass ``` -nesse caso, o `decorador1` decora o `decorador2` que decora a função `funcao_que_redece_dois_decoradores`. Sim, eu sei que você entendeu e isso pode ter um ciclo infinito de possibilidades. Uma coisa que deve ser levada em consideração é que conforme você aninha decoradores as funções tendem a ficar mais dificeis de depurar e de prever o comportamento. +nesse caso, o `decorador1` decora o `decorador2` que decora a função `funcao_que_recebe_dois_decoradores`. Sim, eu sei que você entendeu e isso pode ter um ciclo infinito de possibilidades. Uma coisa que deve ser levada em consideração é que conforme você aninha decoradores as funções tendem a ficar mais difíceis de depurar e de prever o comportamento. E com isso terminamos aqui a primeira parte do nosso conteúdo sobre programação funcional sem imports. Tudo que construímos até aqui foi usando as funções [builtin](https://docs.python.org/3/library/functions.html#built-in-funcs) do python. Mas antes de prosseguir, gostaria de fazer algumas breves considerações matemáticas, para que seja possível criarmos código de mais qualidade.