Noções básicas de Python
Tags: beginners, python
Published: 2021-07-01 00:25:03

## Padronização

Nomes de váriaveis e métodos são separados por underscore(`_`), em vez de usar o *CamelCase*. Ex: `my_name`, `get_my_name`.

## Método

Estrutura:
```py
def sum(n1, n2):
	return n1 + n2
```

### Parâmetros Opcionais

Para um parâmetro de um método ser opcional, basta adicionar um valor padrão. Ex.:
```py
def sum(n1, n2 = 0):
	return n1 + n2
```


### Inferência de Tipos

Estrutura:
```py
def sum(n1: int, n2: int) -> int:
	return n1 + n2
```

### Documentação do método (`docstring`)

Uma `docstring` é uma string no início de uma função que explica o método. Por convenção, todas as `docstrings` têm aspas triplas (**"""**).

Estrutura:
```py
def sum(n1, n2):
    """Soma dois números, e retorna o resultado."""
    return n1 + n2
```


## Classe

Estrutura:
```py
class Animal:
	cont = 0 # class variable shared by all instances

    def __init__(self, name, color):
        self.name = name # instance variable unique to each instance
        self.color = color # instance variable unique to each instance
    
    def greeting(self):
    	print('Oi! Eu sou o ${name}.')
```

Explicações:
- O método `__init__` é o contrutor da classe;
- Qualquer método da classe que precise utilizar algum atributo da classe deve receber `self` na assinatura do método;
- Qualquer variável que apareça fora do método `__init__` é compartilhada entre todas as instâncias dessa classe, como é o caso da váriavel `cont`. Por exemplo: 
```py
a = Animal()
b = Animal()
a.cont = 3
b.cont = 5
print(a.cont) # 5
print(b.cont) # 5
```

### Tipo de Acesso

Segundo a [documentação do python](https://docs.python.org/pt-br/3/tutorial/classes.html): Variáveis de instância e metodos *“privadas”*, que não podem ser acessadas, exceto em métodos do próprio objeto, *não existem* em Python. No entanto, existe uma convenção que é seguida pela maioria dos programas em Python: um nome prefixado com um underscore (por exemplo: `_spam` e `_set_age(self, new_age)`). Dessa forma, em vez de chama-los de "privados", nomea-se "não-públicos".



### Getters e Setters
Em muitos casos é necessário adicionar regras de negócio, a alguns dados, isto é, alterar ou obter algum atributo da classe, somente se atender a certas regras da classe.
Com esse objetivo, basta seguir os seguintes passos:
1. Defina o atributo como *privado* (adicione o underline na frente do atributo);
2. Crie suas funções de getter e setter, com o nome do atributo. Ex.: Para o atributo `_name`, tanto o método getter como o setter, terão o nome `name`.
3. Adicione `@property` em cima dos métodos getters, e `@nome_do_atributo.setter` em cima dos métodos setters . 


### Enum

Estrutura:
```py
from enum import Enum

class Color(Enum):
    WHITE = 0
    GRAY = 1
    BLACK = 2
```


### Herança

*Obs.*: Suporta herança múltipla.

Estrutura:
```py
class Animal:
	cont = 0

    def __init__(self, name, color):
        self.name = name
        self.color = color

class Duck:
	cont = 0

    def __init__(self, name, color, other):
        super().__init__(name, color)
        self.other = other
```


## Importando Arquivos

Estrutura:
```py
import animal
from src.routes.index import Routes # importa Routes da pasta src/routes/index. Obs.:

a = animal.Animal
routes = Routes()
```

*Obs.:* Quando fazemos `from src.routes.index import Routes`, estamos importando `Routes` da pasta `src/routes/index`. Esse é um caminho para encontrar esse arquivo, mas não significa que está em uma subpasta. Pelo contrário, é possível que essa pasta `src` pode ser uma pasta anterior, ou do diretório atual.


## Lista e Dicionário

### List ou Array

```py
my_integers = [1, 2, 3, 4, 5]
```
*Obs.*: Pode-se criar um array não vazio e iniciado com alguns valores padrão. Exemplo:
```py
array_of_ones = [1] * 4 # [1,1,1,1]
array_of_0_4 = [i for i in range(5)] # [0,1,2,3,4]
```

### Sets

Como o próprio nome diz, refere-se a uma lista de elementos (arrodeado por chaves) sem repetição. Para criar um conjunto, passando um conjunto:
```py
my_integers = {1, 2, 3, 4, 5}
```
, ou através da função `set()`. Essa função retorna um conjunto, e pode receber um argumento iterável (ex.: listas), transformando-o em um conjunto. Já se não passarmos nenhum elemento, ele retorna um conjunto vazio.
```py
my_integers = set([1, 2, 3, 4, 5])
```

### Dictionary Estrutura de Dados de Chave-Valor
```py
dictionary_example = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}
dictionary_example["key1"]
```
*Obs.:* A expressão `{}` é considerada um dicionário vazio, e não um conjunto


## Outros

### Operador ternário
```py
x = b if (b > a) else a
```

### Retornando um valor dependendo do primeiro
```py
x = False or 32
print(x) # 32
x = {} or 32
print(x) # 32
x = [] or 32
print(x) # 32
```


Referências:
- [Learning Python: From Zero to Hero](https://www.freecodecamp.org/news/learning-python-from-zero-to-hero-120ea540b567/)
- [docs.python: Classes](https://docs.python.org/pt-br/3/tutorial/classes.html)
- [Pense em Python](https://pense-python.caravela.club/)