---
# System prepended metadata

title: Untitled

---

##     É hora da história!

Imagine que o Branda chegou para você e disse:
    - Preciso de uma função que retorne as espécies favoritas de cada programador de CORP!

Pensando nisso, você escreve o seguinte código:
Ele vai receber o nome do programador, e baseado nisso, retornar as espécies favoritas. Todavia, se você quiser, pode já fornecer algumas espécies que você sabe que o programador gosta.

```python
def get_favorite_species(coder, favorites=[]):
    if coder in ['kamm', 'veloso', 'mentz']:
        favorites.append('dairy') 

    if coder in ['gaspa', 'cuchi']:
        favorites.append('layers') 

    if coder == 'mary':
        favorites.append('broiler') 

    return favorites
```

## Show! Finalizado. É hora de testar:
> ​​  
> Bora começar por mim! Eu já queria dizer de cara: Amo porquinhos! Bora ver o que acontece.
> ```python
> print(get_favorite_species('kamm', favorites=['swine']))
> > ['swine', 'dairy']
> ```
> Tudo parece estar funcionando! Bora codar mais. Agora, vou adicionar o Gaspa! Não sei nenhuma espécie favorita dele...
> 
> ```python
> print(get_favorite_species('kamm', favorites=['swine']))
> > ['swine', 'dairy']
> 
> print(get_favorite_species('gaspa'))
> > ['layers']
> ```
> Funcionou com o gaspa! Bora testar com a mary!
>
> ```python
> print(get_favorite_species('kamm', favorites=['swine']))
> > ['swine', 'dairy']
> 
> print(get_favorite_species('gaspa'))
> > ['layers']
> 
> print(get_favorite_species('mary'))
> > ['layers', 'broiler']
> ```
> 
> Xiii... como assim a Mary gosta de layers? Esse não era o gaspa? Deveria ser apenas broiler...  
>​

## Explicação:

Ao definir a função `get_favorite_species`, decidimos fornecer um valor default para o argumento `favorites`.  
Então, quando você rodar o seu arquivo `.py` pela primeira vez (ou subir seu `Django/Flask`), 
ele vai salvar um "ponteiro" para essa lista chamada `favorites`.  
(Ou seja, uma única referência para `favorites` que vai ser usada toda vez que essa função ser chamada)

Visto isso, vamos entender o que acontece em cada uma dessas linhas:  

```python
"""
    Nessa linha, fornecemos um 'favorites' já conhecido. Falando sobre a parte técnica, isso irá sobreescrever o favorites da assinatura da função. Ou seja, não será usada a referência original de favoritas iniciado vazio, e sim uim objeto que nós estamos fornecendo.

    Como resultado, temos o output esperado. 
"""
print(get_favorite_species('kamm', favorites=['swine']))

"""
    Nessa linha, não fornecemos nenhum 'favorites'. Isso significa que iremos utilizar internamente o 'favorites' default (Aquela referência a uma lista vazia, criada quando vc subiu seu arquivo .py)

    Inicialmente, de fato ela é vazia. Então, anteriormente o favorites=[], irá ser MUTADO para ['layers'].
    Todavia, o pronto crítico é: Essa lista era uma REFERÊNCIA.
    Ao terminar a execução dessa linha, a lista 'favorites' AINDA terá ['layers'] dentro.
"""
print(get_favorite_species('gaspa'))

"""
    Nessa linha, não fornecemos nenhum 'favorites'. Isso significa que iremos utilizar internamente o 'favorites' default.

    Esse, por sua vez, foi mutado anteriormente, e é: ['layers']
    Ao adicionar mais uma espécie, (a da mary), temos o resultado estranho. 
"""
print(get_favorite_species('mary'))
```

---
## Solução

```python
def get_favorite_species_fixed(coder, favorites=None):
    if not favorites:
        favorites = []

    if coder in ['kamm', 'veloso', 'mentz']:
        favorites.append('dairy') 

    if coder in ['gaspa', 'cuchi']:
        favorites.append('layers') 

    if coder == 'mary':
        favorites.append('broiler') 

    return favorites
```

A solução é: **Devemos ter cuidado ao usar objetos mutáveis como argumentos default.**  
Nesse caso, usandos uma lista (que é mutável), mas esse erro também iria ocorrer para dicionários.  

Você pode testar o código aqui:
- [Código das duas funções](https://replit.com/@ViniciusKammrad/ExemplosMutavel#main.py)  

Documentações:
- https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/
- https://docs.python-guide.org/writing/gotchas/